mirror of
https://github.com/Tencent/MMKV.git
synced 2026-10-17 04:30:56 +08:00
add docs for flutter
This commit is contained in:
@@ -5,3 +5,4 @@
|
||||
.pub/
|
||||
|
||||
build/
|
||||
doc/
|
||||
|
||||
+146
-232
@@ -1,287 +1,201 @@
|
||||
[](https://github.com/Tencent/MMKV/blob/master/LICENSE.TXT)
|
||||
[](https://github.com/Tencent/MMKV/pulls)
|
||||
[](https://github.com/Tencent/MMKV/releases)
|
||||
[](https://github.com/Tencent/MMKV/wiki/home)
|
||||
[](https://github.com/Tencent/MMKV/releases)
|
||||
[](https://github.com/Tencent/MMKV/wiki/home)
|
||||
|
||||
中文版本请参看[这里](./readme_cn.md)
|
||||
MMKV is an **efficient**, **small**, **easy-to-use** mobile key-value storage framework used in the WeChat application. It's currently available on **Android** and **iOS**.
|
||||
|
||||
MMKV is an **efficient**, **small**, **easy-to-use** mobile key-value storage framework used in the WeChat application. It's currently available on **Android**, **iOS/macOS**, **Win32** and **POSIX**.
|
||||
|
||||
# MMKV for Android
|
||||
# MMKV for Flutter
|
||||
|
||||
## Features
|
||||
|
||||
* **Efficient**. MMKV uses mmap to keep memory synced with file, and protobuf to encode/decode values, making the most of Android to achieve best performance.
|
||||
* **Efficient**. MMKV uses mmap to keep memory synced with file, and protobuf to encode/decode values, making the most of native platform to achieve best performance.
|
||||
* **Multi-Process concurrency**: MMKV supports concurrent read-read and read-write access between processes.
|
||||
|
||||
* **Easy-to-use**. You can use MMKV as you go. All changes are saved immediately, no `sync`, no `apply` calls needed.
|
||||
|
||||
* **Small**.
|
||||
* **A handful of files**: MMKV contains process locks, encode/decode helpers and mmap logics and nothing more. It's really tidy.
|
||||
* **About 50K in binary size**: MMKV adds about 50K per architecture on App size, and much less when zipped (apk).
|
||||
* **About 100K in binary size**: MMKV adds about 100K per architecture on App size, and much less when zipped (apk/ipa).
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation Via Maven
|
||||
Add the following lines to `build.gradle` on your app module:
|
||||
### Installation
|
||||
Add the following lines to `pubspec.yaml` on your app module:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
MMKVFlutter: ">=1.2.5"
|
||||
...
|
||||
```
|
||||
|
||||
Note: MMKV for Flutter works perfectly with the native MMKV lib you already used on your App. All you have to do is upgrade to version newer than v1.2.5.
|
||||
However, if you previously use `com.tencent.mmkv` in your Android App, you should move to `com.tencent.mmkv-static`.
|
||||
And if your App depends on any 3rd SDK that embeds `com.tencent.mmkv`, you can add this lines to your `build.gradle` to avoid conflict:
|
||||
```gradle
|
||||
dependencies {
|
||||
implementation 'com.tencent:mmkv-static:1.2.4'
|
||||
// replace "1.2.4" with any available version
|
||||
}
|
||||
dependencies {
|
||||
...
|
||||
|
||||
modules {
|
||||
module("com.tencent:mmkv") {
|
||||
replacedBy("com.tencent:mmkv-static", "Using mmkv-static for flutter")
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For other installation options, see [Android Setup](https://github.com/Tencent/MMKV/wiki/android_setup).
|
||||
|
||||
### Quick Tutorial
|
||||
### Setup
|
||||
You can use MMKV as you go. All changes are saved immediately, no `sync`, no `apply` calls needed.
|
||||
Setup MMKV on App startup, say your `Application` class, add these lines:
|
||||
Setup MMKV on App startup, say your `main()` function, add these lines:
|
||||
|
||||
```Java
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
```dart
|
||||
import 'package:MMKVFlutter/mmkv.dart';
|
||||
|
||||
String rootDir = MMKV.initialize(this);
|
||||
System.out.println("mmkv root: " + rootDir);
|
||||
//……
|
||||
void main() async {
|
||||
|
||||
// must wait for MMKV to finish initialization
|
||||
final rootDir = await MMKV.initialize();
|
||||
print('MMKV for flutter with rootDir = $rootDir');
|
||||
|
||||
runApp(MyApp());
|
||||
}
|
||||
```
|
||||
Note that you have to **wait for MMKV to finish initialization** before accessing any MMKV instance.
|
||||
|
||||
MMKV has a global instance, that can be used directly:
|
||||
### CRUD Operations
|
||||
|
||||
```Java
|
||||
import com.tencent.mmkv.MMKV;
|
||||
* MMKV has a global instance, that can be used directly:
|
||||
|
||||
```dart
|
||||
import 'package:MMKVFlutter/mmkv.dart';
|
||||
|
||||
var mmkv = MMKV.defaultMMKV();
|
||||
mmkv.encodeBool('bool', true);
|
||||
print('bool = ${mmkv.decodeBool('bool')}');
|
||||
|
||||
MMKV kv = MMKV.defaultMMKV();
|
||||
|
||||
kv.encode("bool", true);
|
||||
boolean bValue = kv.decodeBool("bool");
|
||||
|
||||
kv.encode("int", Integer.MIN_VALUE);
|
||||
int iValue = kv.decodeInt("int");
|
||||
|
||||
kv.encode("string", "Hello from mmkv");
|
||||
String str = kv.decodeString("string");
|
||||
```
|
||||
|
||||
MMKV also supports **Multi-Process Access**. Full tutorials can be found here [Android Tutorial](https://github.com/Tencent/MMKV/wiki/android_tutorial).
|
||||
|
||||
## Performance
|
||||
Writing random `int` for 1000 times, we get this chart:
|
||||

|
||||
For more benchmark data, please refer to [our benchmark](https://github.com/Tencent/MMKV/wiki/android_benchmark).
|
||||
|
||||
# MMKV for iOS/macOS
|
||||
|
||||
## Features
|
||||
|
||||
* **Efficient**. MMKV uses mmap to keep memory synced with file, and protobuf to encode/decode values, making the most of iOS/macOS to achieve best performance.
|
||||
|
||||
* **Easy-to-use**. You can use MMKV as you go, no configurations needed. All changes are saved immediately, no `synchronize` calls needed.
|
||||
|
||||
* **Small**.
|
||||
* **A handful of files**: MMKV contains encode/decode helpers and mmap logics and nothing more. It's really tidy.
|
||||
* **Less than 30K in binary size**: MMKV adds less than 30K per architecture on App size, and much less when zipped (ipa).
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation Via CocoaPods:
|
||||
1. Install [CocoaPods](https://guides.CocoaPods.org/using/getting-started.html);
|
||||
2. Open terminal, `cd` to your project directory, run `pod repo update` to make CocoaPods aware of the latest available MMKV versions;
|
||||
3. Edit your Podfile, add `pod 'MMKV'` to your app target;
|
||||
4. Run `pod install`;
|
||||
5. Open the `.xcworkspace` file generated by CocoaPods;
|
||||
6. Add `#import <MMKV/MMKV.h>` to your source file and we are done.
|
||||
|
||||
For other installation options, see [iOS/macOS Setup](https://github.com/Tencent/MMKV/wiki/iOS_setup).
|
||||
|
||||
### Quick Tutorial
|
||||
You can use MMKV as you go, no configurations needed. All changes are saved immediately, no `synchronize` calls needed.
|
||||
Setup MMKV on App startup, in your `-[MyApp application: didFinishLaunchingWithOptions:]`, add these lines:
|
||||
|
||||
```objective-c
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// init MMKV in the main thread
|
||||
[MMKV initializeMMKV:nil];
|
||||
|
||||
//...
|
||||
return YES;
|
||||
}
|
||||
```
|
||||
|
||||
MMKV has a global instance, that can be used directly:
|
||||
|
||||
```objective-c
|
||||
MMKV *mmkv = [MMKV defaultMMKV];
|
||||
mmkv.encodeInt32('int32', (1<<31) - 1);
|
||||
print('max int32 = ${mmkv.decodeInt32('int32')}');
|
||||
|
||||
[mmkv setBool:YES forKey:@"bool"];
|
||||
BOOL bValue = [mmkv getBoolForKey:@"bool"];
|
||||
mmkv.encodeInt('int', (1<<63) - 1);
|
||||
print('max int = ${mmkv.decodeInt('int')}');
|
||||
|
||||
[mmkv setInt32:-1024 forKey:@"int32"];
|
||||
int32_t iValue = [mmkv getInt32ForKey:@"int32"];
|
||||
|
||||
[mmkv setString:@"hello, mmkv" forKey:@"string"];
|
||||
NSString *str = [mmkv getStringForKey:@"string"];
|
||||
```
|
||||
String str = 'Hello Flutter from MMKV';
|
||||
mmkv.encodeString('string', str);
|
||||
print('string = ${mmkv.decodeString('string')}');
|
||||
|
||||
MMKV also supports **Multi-Process Access**. Full tutorials can be found [here](https://github.com/Tencent/MMKV/wiki/iOS_tutorial).
|
||||
str = 'Hello Flutter from MMKV with bytes';
|
||||
var bytes = MMBuffer.fromList(Utf8Encoder().convert(str));
|
||||
mmkv.encodeBytes('bytes', bytes);
|
||||
bytes.destroy();
|
||||
|
||||
## Performance
|
||||
Writing random `int` for 10000 times, we get this chart:
|
||||

|
||||
For more benchmark data, please refer to [our benchmark](https://github.com/Tencent/MMKV/wiki/iOS_benchmark).
|
||||
|
||||
|
||||
# MMKV for Win32
|
||||
|
||||
## Features
|
||||
|
||||
* **Efficient**. MMKV uses mmap to keep memory synced with file, and protobuf to encode/decode values, making the most of Windows to achieve best performance.
|
||||
* **Multi-Process concurrency**: MMKV supports concurrent read-read and read-write access between processes.
|
||||
|
||||
* **Easy-to-use**. You can use MMKV as you go. All changes are saved immediately, no `save`, no `sync` calls needed.
|
||||
|
||||
* **Small**.
|
||||
* **A handful of files**: MMKV contains process locks, encode/decode helpers and mmap logics and nothing more. It's really tidy.
|
||||
* **About 10K in binary size**: MMKV adds about 10K on application size, and much less when zipped.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation Via Source
|
||||
1. Getting source code from git repository:
|
||||
|
||||
```
|
||||
git clone https://github.com/Tencent/MMKV.git
|
||||
```
|
||||
|
||||
2. Add `Win32/MMKV/MMKV.vcxproj` to your solution;
|
||||
3. Add `MMKV` project to your project's dependencies;
|
||||
4. Add `$(OutDir)include` to your project's `C/C++` -> `General` -> `Additional Include Directories`;
|
||||
5. Add `$(OutDir)` to your project's `Linker` -> `General` -> `Additional Library Directories`;
|
||||
6. Add `MMKV.lib` to your project's `Linker` -> `Input` -> `Additional Dependencies`;
|
||||
7. Add `#include <MMKV/MMKV.h>` to your source file and we are done.
|
||||
|
||||
|
||||
note:
|
||||
|
||||
1. MMKV is compiled with `MT/MTd` runtime by default. If your project uses `MD/MDd`, you should change MMKV's setting to match your project's (`C/C++` -> `Code Generation` -> `Runtime Library`), or vise versa.
|
||||
2. MMKV is developed with Visual Studio 2017, change the `Platform Toolset` if you use a different version of Visual Studio.
|
||||
|
||||
For other installation options, see [Win32 Setup](https://github.com/Tencent/MMKV/wiki/windows_setup).
|
||||
|
||||
### Quick Tutorial
|
||||
You can use MMKV as you go. All changes are saved immediately, no `sync`, no `save` calls needed.
|
||||
Setup MMKV on App startup, say in your `main()`, add these lines:
|
||||
|
||||
```C++
|
||||
#include <MMKV/MMKV.h>
|
||||
|
||||
int main() {
|
||||
std::wstring rootDir = getYourAppDocumentDir();
|
||||
MMKV::initializeMMKV(rootDir);
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
MMKV has a global instance, that can be used directly:
|
||||
|
||||
```C++
|
||||
auto mmkv = MMKV::defaultMMKV();
|
||||
|
||||
mmkv->set(true, "bool");
|
||||
std::cout << "bool = " << mmkv->getBool("bool") << std::endl;
|
||||
|
||||
mmkv->set(1024, "int32");
|
||||
std::cout << "int32 = " << mmkv->getInt32("int32") << std::endl;
|
||||
|
||||
mmkv->set("Hello, MMKV for Win32", "string");
|
||||
std::string result;
|
||||
mmkv->getString("string", result);
|
||||
std::cout << "string = " << result << std::endl;
|
||||
```
|
||||
|
||||
MMKV also supports **Multi-Process Access**. Full tutorials can be found here [Win32 Tutorial](https://github.com/Tencent/MMKV/wiki/windows_tutorial).
|
||||
|
||||
# MMKV for POSIX
|
||||
|
||||
## Features
|
||||
|
||||
* **Efficient**. MMKV uses mmap to keep memory synced with file, and protobuf to encode/decode values, making the most of POSIX to achieve best performance.
|
||||
* **Multi-Process concurrency**: MMKV supports concurrent read-read and read-write access between processes.
|
||||
|
||||
* **Easy-to-use**. You can use MMKV as you go. All changes are saved immediately, no `save`, no `sync` calls needed.
|
||||
|
||||
* **Small**.
|
||||
* **A handful of files**: MMKV contains process locks, encode/decode helpers and mmap logics and nothing more. It's really tidy.
|
||||
* **About 7K in binary size**: MMKV adds about 7K on application size, and much less when zipped.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation Via CMake
|
||||
1. Getting source code from git repository:
|
||||
|
||||
```
|
||||
git clone https://github.com/Tencent/MMKV.git
|
||||
```
|
||||
2. Edit your `CMakeLists.txt`, add those lines:
|
||||
|
||||
```cmake
|
||||
add_subdirectory(mmkv/POSIX/src mmkv)
|
||||
target_link_libraries(MyApp
|
||||
mmkv)
|
||||
bytes = mmkv.decodeBytes('bytes');
|
||||
print('bytes = ${Utf8Decoder().convert(bytes.asList())}');
|
||||
bytes.destroy();
|
||||
```
|
||||
3. Add `#include "MMKV.h"` to your source file and we are done.
|
||||
|
||||
For other installation options, see [POSIX Setup](https://github.com/Tencent/MMKV/wiki/posix_setup).
|
||||
As you can see, MMKV is quite easy to use.
|
||||
|
||||
* **Deleting & Querying**:
|
||||
|
||||
### Quick Tutorial
|
||||
You can use MMKV as you go. All changes are saved immediately, no `sync`, no `save` calls needed.
|
||||
Setup MMKV on App startup, say in your `main()`, add these lines:
|
||||
```dart
|
||||
var mmkv = MMKV.defaultMMKV();
|
||||
|
||||
```C++
|
||||
#include "MMKV.h"
|
||||
mmkv.removeValue('bool');
|
||||
print('contains "bool": ${mmkv.containsKey('bool')}');
|
||||
|
||||
int main() {
|
||||
std::string rootDir = getYourAppDocumentDir();
|
||||
MMKV::initializeMMKV(rootDir);
|
||||
//...
|
||||
}
|
||||
```
|
||||
mmkv.removeValues(['int32', 'int']);
|
||||
print('all keys: ${mmkv.allKeys}');
|
||||
```
|
||||
|
||||
MMKV has a global instance, that can be used directly:
|
||||
* If different modules/logic need **isolated storage**, you can also create your own MMKV instance separately:
|
||||
|
||||
```C++
|
||||
auto mmkv = MMKV::defaultMMKV();
|
||||
```dart
|
||||
var mmkv = MMKV("test");
|
||||
mmkv.encodeBool('bool', true);
|
||||
print('bool = ${mmkv.decodeBool('bool')}');
|
||||
```
|
||||
|
||||
mmkv->set(true, "bool");
|
||||
std::cout << "bool = " << mmkv->getBool("bool") << std::endl;
|
||||
* If **multi-process accessing** is needed,you can set `MMKV.MULTI_PROCESS_MODE` on MMKV initialization:
|
||||
|
||||
mmkv->set(1024, "int32");
|
||||
std::cout << "int32 = " << mmkv->getInt32("int32") << std::endl;
|
||||
```dart
|
||||
var mmkv = MMKV("test-multi-process", mode: MMKVMode.MULTI_PROCESS_MODE);
|
||||
mmkv.encodeBool('bool', true);
|
||||
print('bool = ${mmkv.decodeBool('bool')}');
|
||||
```
|
||||
|
||||
mmkv->set("Hello, MMKV for Win32", "string");
|
||||
std::string result;
|
||||
mmkv->getString("string", result);
|
||||
std::cout << "string = " << result << std::endl;
|
||||
```
|
||||
### Supported Types
|
||||
* Primitive Types:
|
||||
- `bool, int, double`
|
||||
|
||||
* Classes & Collections:
|
||||
- `String, List<int>, MMBuffer`
|
||||
|
||||
### Log
|
||||
|
||||
* By default, MMKV prints log to logcat/console, which is not convenient for diagnosing online issues.
|
||||
You can setup MMKV **log redirecting** on App startup on the **native** interface of MMKV.
|
||||
Checkout how to do it on [Android](https://github.com/Tencent/MMKV/wiki/android_advance#log) / [iOS](https://github.com/Tencent/MMKV/wiki/ios_advance#log).
|
||||
Due to the current limitation of Flutter runtime, we can't redirect log on the Flutter side.
|
||||
|
||||
* You can turn off MMKV's logging once and for all on initialization (which we strongly disrecommend).
|
||||
|
||||
```dart
|
||||
final rootDir = await MMKV.initialize(logLevel: MMKVLogLevel.None);
|
||||
```
|
||||
### Encryption
|
||||
* By default MMKV stores all key-values in plain text on file, relying on Android's/iOS's sandbox to make sure the file is encrypted. Should you worry about information leaking, you can choose to encrypt MMKV.
|
||||
|
||||
```dart
|
||||
final encryptKey = 'MyEncryptKey';
|
||||
var mmkv = MMKV("test-encryption", cryptKey: encryptKey);
|
||||
```
|
||||
|
||||
* You can change the encryption key later as you like. You can also change an existing MMKV instance from encrypted to unencrypted, or vice versa.
|
||||
|
||||
```dart
|
||||
// an unencrypted MMKV instance
|
||||
var mmkv = MMKV("test-encryption");
|
||||
|
||||
// change from unencrypted to encrypted
|
||||
mmkv.reKey("Key_seq_1");
|
||||
|
||||
// change encryption key
|
||||
mmkv.reKey("Key_seq_2");
|
||||
|
||||
// change from encrypted to unencrypted
|
||||
kmmkv.reKey(null);
|
||||
```
|
||||
|
||||
### Customize location
|
||||
* By default, MMKV stores file inside `$(FilesDir)/mmkv/`. You can customize MMKV's **root directory** on App startup:
|
||||
|
||||
```dart
|
||||
final dir = await getApplicationSupportDirectory();
|
||||
final rootDir = await MMKV.initialize(dir, rootDir: dir.path + '/mmkv_2');
|
||||
print('MMKV for flutter with rootDir = $rootDir');
|
||||
```
|
||||
|
||||
* You can even customize any MMKV instance's location:
|
||||
|
||||
```dart
|
||||
final dir = await getApplicationSupportDirectory();
|
||||
var mmkv = MMKV('testCustomDir', rootDir: dir.path + '/mmkv_3');
|
||||
```
|
||||
**Note:** It's recommended to store MMKV files **inside** your App's sandbox path. **DO NOT** store them on external storage(aka SD card). If you have to do it, you should follow Android's [scoped storage](https://developer.android.com/preview/privacy/storage) enforcement.
|
||||
|
||||
MMKV also supports **Multi-Process Access**. Full tutorials can be found here [POSIX Tutorial](https://github.com/Tencent/MMKV/wiki/posix_tutorial).
|
||||
|
||||
## License
|
||||
MMKV is published under the BSD 3-Clause license. For details check out the [LICENSE.TXT](./LICENSE.TXT).
|
||||
MMKV is published under the BSD 3-Clause license. For details check out the [LICENSE.TXT](https://github.com/Tencent/MMKV/blob/master/LICENSE.TXT).
|
||||
|
||||
## Change Log
|
||||
Check out the [CHANGELOG.md](./CHANGELOG.md) for details of change history.
|
||||
Check out the [CHANGELOG.md](https://github.com/Tencent/MMKV/blob/master/flutter/CHANGELOG.md) for details of change history.
|
||||
|
||||
## Contributing
|
||||
|
||||
If you are interested in contributing, check out the [CONTRIBUTING.md](./CONTRIBUTING.md), also join our [Tencent OpenSource Plan](https://opensource.tencent.com/contribution).
|
||||
If you are interested in contributing, check out the [CONTRIBUTING.md](https://github.com/Tencent/MMKV/blob/master/CONTRIBUTING.md), also join our [Tencent OpenSource Plan](https://opensource.tencent.com/contribution).
|
||||
|
||||
To give clarity of what is expected of our members, MMKV has adopted the code of conduct defined by the Contributor Covenant, which is widely used. And we think it articulates our values well. For more, check out the [Code of Conduct](./CODE_OF_CONDUCT.md).
|
||||
To give clarity of what is expected of our members, MMKV has adopted the code of conduct defined by the Contributor Covenant, which is widely used. And we think it articulates our values well. For more, check out the [Code of Conduct](https://github.com/Tencent/MMKV/blob/master/CODE_OF_CONDUCT.md).
|
||||
|
||||
## FAQ & Feedback
|
||||
Check out the [FAQ](https://github.com/Tencent/MMKV/wiki/FAQ) first. Should there be any questions, don't hesitate to create [issues](https://github.com/Tencent/MMKV/issues).
|
||||
|
||||
@@ -24,7 +24,6 @@ import 'dart:convert';
|
||||
import 'package:MMKVFlutter/mmkv.dart';
|
||||
|
||||
void main() async {
|
||||
|
||||
// must wait for MMKV to finish initialization
|
||||
final rootDir = await MMKV.initialize();
|
||||
print('MMKV for flutter with rootDir = $rootDir');
|
||||
@@ -38,7 +37,6 @@ class MyApp extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -62,16 +60,16 @@ class _MyAppState extends State<MyApp> {
|
||||
mmkv.encodeBool('bool', true);
|
||||
print('bool = ${mmkv.decodeBool('bool')}');
|
||||
|
||||
mmkv.encodeInt32('int32', (1<<31) - 1);
|
||||
mmkv.encodeInt32('int32', (1 << 31) - 1);
|
||||
print('max int32 = ${mmkv.decodeInt32('int32')}');
|
||||
|
||||
mmkv.encodeInt32('int32', 0 - (1<<31));
|
||||
mmkv.encodeInt32('int32', 0 - (1 << 31));
|
||||
print('min int32 = ${mmkv.decodeInt32('int32')}');
|
||||
|
||||
mmkv.encodeInt('int', (1<<63) - 1);
|
||||
mmkv.encodeInt('int', (1 << 63) - 1);
|
||||
print('max int = ${mmkv.decodeInt('int')}');
|
||||
|
||||
mmkv.encodeInt('int', 0 - (1<<63));
|
||||
mmkv.encodeInt('int', 0 - (1 << 63));
|
||||
print('min int = ${mmkv.decodeInt('int')}');
|
||||
|
||||
mmkv.encodeDouble('double', double.maxFinite);
|
||||
@@ -96,13 +94,13 @@ class _MyAppState extends State<MyApp> {
|
||||
mmkv.removeValue('bool');
|
||||
print('after remove, contains "bool": ${mmkv.containsKey('bool')}');
|
||||
mmkv.removeValues(['int32', 'int']);
|
||||
print('all keys: ${mmkv.allKeys()}');
|
||||
print('all keys: ${mmkv.allKeys}');
|
||||
|
||||
mmkv.trim();
|
||||
mmkv.clearMemoryCache();
|
||||
print('all keys: ${mmkv.allKeys()}');
|
||||
print('all keys: ${mmkv.allKeys}');
|
||||
mmkv.clearAll();
|
||||
print('all keys: ${mmkv.allKeys()}');
|
||||
print('all keys: ${mmkv.allKeys}');
|
||||
// mmkv.sync(true);
|
||||
// mmkv.close();
|
||||
}
|
||||
@@ -115,12 +113,9 @@ class _MyAppState extends State<MyApp> {
|
||||
title: const Text('Plugin example app'),
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
// Text('Running on: $_platformVersion\n'),
|
||||
]
|
||||
)
|
||||
),
|
||||
child: Column(children: <Widget>[
|
||||
// Text('Running on: $_platformVersion\n'),
|
||||
])),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
+290
-147
@@ -19,53 +19,55 @@
|
||||
*/
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:ffi'; // For FFI
|
||||
import 'dart:io'; // For Platform.isX
|
||||
import 'dart:typed_data';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
enum MMKVLogLevel {
|
||||
Debug,
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
None
|
||||
}
|
||||
/// Log level for MMKV.
|
||||
enum MMKVLogLevel { Debug, Info, Warning, Error, None }
|
||||
|
||||
/// Process mode for MMKV, default to [SINGLE_PROCESS_MODE].
|
||||
enum MMKVMode {
|
||||
INVALID_MODE,
|
||||
SINGLE_PROCESS_MODE,
|
||||
MULTI_PROCESS_MODE,
|
||||
}
|
||||
|
||||
// a native memory buffer, must call destroy() after no longer use
|
||||
/// A native memory buffer, must call [MMBuffer.destroy()] after no longer use.
|
||||
class MMBuffer {
|
||||
int _length;
|
||||
|
||||
/// The size of the memory buffer.
|
||||
int get length => _length;
|
||||
|
||||
Pointer<Uint8> _ptr;
|
||||
|
||||
/// The pointer of underlying memory buffer.
|
||||
Pointer<Uint8> get pointer => _ptr;
|
||||
|
||||
MMBuffer(int size) {
|
||||
_length = size;
|
||||
if (size > 0) {
|
||||
_ptr = allocate<Uint8>(count: size);
|
||||
/// Create a memory buffer with size of [length].
|
||||
MMBuffer(int length) {
|
||||
_length = length;
|
||||
if (length > 0) {
|
||||
_ptr = allocate<Uint8>(count: length);
|
||||
}
|
||||
}
|
||||
|
||||
// copy all data from list
|
||||
/// Copy all data from [list].
|
||||
static MMBuffer fromList(List<int> list) {
|
||||
var buffer = MMBuffer(list.length);
|
||||
buffer.asList().setAll(0, list);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/// Create a wrapper of native pointer [ptr] with size [length].
|
||||
/// DON'T [destroy()] the result because it's not a copy.
|
||||
static MMBuffer _fromPointer(Pointer<Uint8> ptr, int length) {
|
||||
var buffer = MMBuffer(0);
|
||||
buffer._length = length;
|
||||
@@ -73,6 +75,8 @@ class MMBuffer {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/// Create a wrapper of native pointer [ptr] with size [length].
|
||||
/// DO remember to [destroy()] the result because it's a COPY.
|
||||
static MMBuffer _copyFromPointer(Pointer<Uint8> ptr, int length) {
|
||||
var buffer = MMBuffer(length);
|
||||
buffer._length = length;
|
||||
@@ -80,15 +84,17 @@ class MMBuffer {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// must call destroy after no longer use
|
||||
/// Must call this after no longer use.
|
||||
void destroy() {
|
||||
if (_ptr != null && _ptr != nullptr) {
|
||||
free(_ptr);
|
||||
}
|
||||
_ptr = null;
|
||||
_length = 0;
|
||||
}
|
||||
|
||||
// get a list view of the underlying data
|
||||
/// Get a **list view** of the underlying data.
|
||||
/// Must call [destroy()] later after not longer use.
|
||||
Uint8List asList() {
|
||||
if (_ptr != null && _ptr != nullptr) {
|
||||
return _ptr.asTypedList(_length);
|
||||
@@ -96,8 +102,8 @@ class MMBuffer {
|
||||
return null;
|
||||
}
|
||||
|
||||
// copy the underlying data as a list
|
||||
// and destroy() self
|
||||
/// Copy the underlying data as a list.
|
||||
/// And [destroy()] itself at the same time.
|
||||
Uint8List takeList() {
|
||||
if (_ptr != null && _ptr != nullptr) {
|
||||
var list = Uint8List.fromList(asList());
|
||||
@@ -108,12 +114,35 @@ class MMBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
/// An efficient, small mobile key-value storage framework developed by WeChat.
|
||||
/// Works on Android & iOS.
|
||||
class MMKV {
|
||||
Pointer<Void> _handle;
|
||||
|
||||
static const MethodChannel _channel = const MethodChannel('mmkv');
|
||||
|
||||
static Future<String> initialize([String rootDir, String groupDir, MMKVLogLevel logLevel = MMKVLogLevel.Info]) async {
|
||||
/// MMKV must be initialized before any usage.
|
||||
///
|
||||
/// Generally speaking you should do this inside `main()`:
|
||||
/// ```dart
|
||||
/// void main() async {
|
||||
/// // must wait for MMKV to finish initialization
|
||||
/// final rootDir = await MMKV.initialize();
|
||||
/// print('MMKV for flutter with rootDir = $rootDir');
|
||||
///
|
||||
/// runApp(MyApp());
|
||||
/// }
|
||||
/// ```
|
||||
/// Note that you must **wait for it** to finish before any usage.
|
||||
/// * You can customize MMKV's root dir by passing [rootDir], `${Document}/mmkv` by default.
|
||||
/// * You can customize MMKV's log level by passing [logLevel].
|
||||
/// You can even turnoff logging by passing [MMKVLogLevel.None], which we don't recommend doing.
|
||||
/// * If you want to use MMKV in multi-process on iOS, you should set group folder by passing [groupDir].
|
||||
/// [groupDir] will be ignored on Android.
|
||||
static Future<String> initialize(
|
||||
{String rootDir,
|
||||
String groupDir,
|
||||
MMKVLogLevel logLevel = MMKVLogLevel.Info}) async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
if (rootDir == null) {
|
||||
@@ -123,8 +152,8 @@ class MMKV {
|
||||
|
||||
if (Platform.isIOS) {
|
||||
final Map<String, dynamic> params = {
|
||||
'rootDir' : rootDir,
|
||||
'logLevel' : logLevel.index,
|
||||
'rootDir': rootDir,
|
||||
'logLevel': logLevel.index,
|
||||
};
|
||||
if (groupDir != null) {
|
||||
params['groupDir'] = groupDir;
|
||||
@@ -139,7 +168,25 @@ class MMKV {
|
||||
}
|
||||
}
|
||||
|
||||
MMKV(String mmapID, [MMKVMode mode = MMKVMode.SINGLE_PROCESS_MODE, String cryptKey, String rootDir]) {
|
||||
/// A generic purpose instance in single-process mode.
|
||||
static MMKV defaultMMKV({String cryptKey}) {
|
||||
var mmkv = MMKV(null);
|
||||
var cryptKeyPtr = _string2Pointer(cryptKey);
|
||||
mmkv._handle = _getDefaultMMKV(cryptKeyPtr);
|
||||
free(cryptKeyPtr);
|
||||
return mmkv;
|
||||
}
|
||||
|
||||
/// Get a MMKV instance with an unique ID [mmapID].
|
||||
///
|
||||
/// * If you want a per-user mmkv, you could merge user-id within [mmapID].
|
||||
/// * You can get a multi-process MMKV instance by passing [MMKVMode.MULTI_PROCESS_MODE].
|
||||
/// * You can encrypt with [cryptKey], which limits to 16 bytes at most.
|
||||
/// * You can customize the [rootDir] of the file.
|
||||
MMKV(String mmapID,
|
||||
{MMKVMode mode = MMKVMode.SINGLE_PROCESS_MODE,
|
||||
String cryptKey,
|
||||
String rootDir}) {
|
||||
if (mmapID != null) {
|
||||
var mmapIDPtr = _string2Pointer(mmapID);
|
||||
var cryptKeyPtr = _string2Pointer(cryptKey);
|
||||
@@ -153,15 +200,7 @@ class MMKV {
|
||||
}
|
||||
}
|
||||
|
||||
static MMKV defaultMMKV([String cryptKey]) {
|
||||
var mmkv = MMKV(null);
|
||||
var cryptKeyPtr = _string2Pointer(cryptKey);
|
||||
mmkv._handle = _getDefaultMMKV(cryptKeyPtr);
|
||||
free(cryptKeyPtr);
|
||||
return mmkv;
|
||||
}
|
||||
|
||||
String mmapID() {
|
||||
String get mmapID {
|
||||
return _pointer2String(_mmapID(_handle));
|
||||
}
|
||||
|
||||
@@ -172,13 +211,15 @@ class MMKV {
|
||||
return _int2Bool(ret);
|
||||
}
|
||||
|
||||
bool decodeBool(String key, [bool defaultValue = false]) {
|
||||
bool decodeBool(String key, {bool defaultValue = false}) {
|
||||
var keyPtr = Utf8.toUtf8(key);
|
||||
var ret = _decodeBool(_handle, keyPtr, _bool2Int(defaultValue));
|
||||
free(keyPtr);
|
||||
return _int2Bool(ret);
|
||||
}
|
||||
|
||||
/// Use this when the [value] won't be larger than a normal int32.
|
||||
/// It's more efficient & cost less space.
|
||||
bool encodeInt32(String key, int value) {
|
||||
var keyPtr = Utf8.toUtf8(key);
|
||||
var ret = _encodeInt32(_handle, keyPtr, value);
|
||||
@@ -186,7 +227,9 @@ class MMKV {
|
||||
return _int2Bool(ret);
|
||||
}
|
||||
|
||||
int decodeInt32(String key, [int defaultValue = 0]) {
|
||||
/// Use this when the value won't be larger than a normal int32.
|
||||
/// It's more efficient & cost less space.
|
||||
int decodeInt32(String key, {int defaultValue = 0}) {
|
||||
var keyPtr = Utf8.toUtf8(key);
|
||||
var ret = _decodeInt32(_handle, keyPtr, defaultValue);
|
||||
free(keyPtr);
|
||||
@@ -200,7 +243,7 @@ class MMKV {
|
||||
return _int2Bool(ret);
|
||||
}
|
||||
|
||||
int decodeInt(String key, [int defaultValue = 0]) {
|
||||
int decodeInt(String key, {int defaultValue = 0}) {
|
||||
var keyPtr = Utf8.toUtf8(key);
|
||||
var ret = _decodeInt64(_handle, keyPtr, defaultValue);
|
||||
free(keyPtr);
|
||||
@@ -214,13 +257,14 @@ class MMKV {
|
||||
return _int2Bool(ret);
|
||||
}
|
||||
|
||||
double decodeDouble(String key, [double defaultValue = 0]) {
|
||||
double decodeDouble(String key, {double defaultValue = 0}) {
|
||||
var keyPtr = Utf8.toUtf8(key);
|
||||
var ret = _decodeDouble(_handle, keyPtr, defaultValue);
|
||||
free(keyPtr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Encode an utf-8 string.
|
||||
bool encodeString(String key, String value) {
|
||||
var keyPtr = Utf8.toUtf8(key);
|
||||
var bytes = MMBuffer.fromList(Utf8Encoder().convert(value));
|
||||
@@ -232,6 +276,7 @@ class MMKV {
|
||||
return _int2Bool(ret);
|
||||
}
|
||||
|
||||
/// Decode as an utf-8 string.
|
||||
String decodeString(String key) {
|
||||
var keyPtr = Utf8.toUtf8(key);
|
||||
Pointer<Uint64> lengthPtr = allocate();
|
||||
@@ -252,6 +297,19 @@ class MMKV {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Encoding bytes.
|
||||
///
|
||||
/// You can serialize an object into bytes, then store it inside MMKV.
|
||||
/// ```dart
|
||||
/// // assume using protobuf https://developers.google.com/protocol-buffers/docs/darttutorial
|
||||
/// var object = MyClass();
|
||||
/// final list = object.writeToBuffer();
|
||||
/// final buffer = MMBuffer.fromList(list);
|
||||
///
|
||||
/// mmkv.encodeBytes('bytes', buffer);
|
||||
///
|
||||
/// buffer.destroy();
|
||||
/// ```
|
||||
bool encodeBytes(String key, MMBuffer value) {
|
||||
var keyPtr = Utf8.toUtf8(key);
|
||||
var ret = _encodeBytes(_handle, keyPtr, value.pointer, value.length);
|
||||
@@ -259,6 +317,20 @@ class MMKV {
|
||||
return _int2Bool(ret);
|
||||
}
|
||||
|
||||
/// Decoding bytes.
|
||||
///
|
||||
/// You can decode bytes from MMKV, then deserialize an object from the bytes.
|
||||
/// ```dart
|
||||
/// // assume using protobuf https://developers.google.com/protocol-buffers/docs/darttutorial
|
||||
/// final bytes = mmkv.decodeBytes('bytes');
|
||||
/// if (bytes != null) {
|
||||
/// final list = bytes.asList();
|
||||
/// final object = MyClass.fromBuffer(list);
|
||||
///
|
||||
/// // Must [destroy()] after no longer use.
|
||||
/// bytes.destroy();
|
||||
/// }
|
||||
/// ```
|
||||
MMBuffer decodeBytes(String key) {
|
||||
var keyPtr = Utf8.toUtf8(key);
|
||||
Pointer<Uint64> lengthPtr = allocate();
|
||||
@@ -279,14 +351,26 @@ class MMKV {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Change encryption key for the MMKV instance.
|
||||
///
|
||||
/// * The [cryptKey] is 16 bytes limited.
|
||||
/// * You can transfer a plain-text MMKV into encrypted by setting an non-null, non-empty [cryptKey].
|
||||
/// * Or vice versa by passing [cryptKey] with null.
|
||||
/// See also [checkReSetCryptKey()].
|
||||
bool reKey(String cryptKey) {
|
||||
var bytes = MMBuffer.fromList(Utf8Encoder().convert(cryptKey));
|
||||
var ret = _reKey(_handle, bytes.pointer, bytes.length);
|
||||
bytes.destroy();
|
||||
return _int2Bool(ret);
|
||||
if (cryptKey != null && cryptKey.length > 0) {
|
||||
var bytes = MMBuffer.fromList(Utf8Encoder().convert(cryptKey));
|
||||
var ret = _reKey(_handle, bytes.pointer, bytes.length);
|
||||
bytes.destroy();
|
||||
return _int2Bool(ret);
|
||||
} else {
|
||||
var ret = _reKey(_handle, nullptr, 0);
|
||||
return _int2Bool(ret);
|
||||
}
|
||||
}
|
||||
|
||||
String cryptKey() {
|
||||
/// See also [reKey()].
|
||||
String get cryptKey {
|
||||
Pointer<Uint64> lengthPtr = allocate();
|
||||
var ret = _cryptKey(_handle, lengthPtr);
|
||||
if (ret != null && ret != nullptr) {
|
||||
@@ -299,12 +383,16 @@ class MMKV {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Just reset the [cryptKey] (will not encrypt or decrypt anything).
|
||||
/// Usually you should call this method after other process [reKey()] the multi-process mmkv.
|
||||
void checkReSetCryptKey(String cryptKey) {
|
||||
var bytes = MMBuffer.fromList(Utf8Encoder().convert(cryptKey));
|
||||
_checkReSetCryptKey(_handle, bytes.pointer, bytes.length);
|
||||
bytes.destroy();
|
||||
}
|
||||
|
||||
/// Get the actual size consumption of the key's value.
|
||||
/// Pass [actualSize] with true to get value's length.
|
||||
int valueSize(String key, bool actualSize) {
|
||||
var keyPtr = Utf8.toUtf8(key);
|
||||
var ret = _valueSize(_handle, keyPtr, _bool2Int(actualSize));
|
||||
@@ -312,14 +400,20 @@ class MMKV {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Write the value to a pre-allocated native buffer.
|
||||
///
|
||||
/// * Return size written into buffer.
|
||||
/// * Return -1 on any error, such as [buffer] not large enough.
|
||||
int writeValueToNativeBuffer(String key, MMBuffer buffer) {
|
||||
var keyPtr = Utf8.toUtf8(key);
|
||||
var ret = _writeValueToNB(_handle, keyPtr, buffer.pointer.cast(), buffer.length);
|
||||
var ret =
|
||||
_writeValueToNB(_handle, keyPtr, buffer.pointer.cast(), buffer.length);
|
||||
free(keyPtr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
List<String> allKeys() {
|
||||
/// Get all the keys (_unsorted_).
|
||||
List<String> get allKeys {
|
||||
Pointer<Pointer<Pointer<Utf8>>> keyArrayPtr = allocate();
|
||||
Pointer<Pointer<Uint32>> sizeArrayPtr = allocate();
|
||||
List<String> keys;
|
||||
@@ -357,15 +451,17 @@ class MMKV {
|
||||
return _int2Bool(ret);
|
||||
}
|
||||
|
||||
int count() {
|
||||
int get count {
|
||||
return _count(_handle);
|
||||
}
|
||||
|
||||
int totalSize() {
|
||||
/// Get the file size. See also [actualSize].
|
||||
int get totalSize {
|
||||
return _totalSize(_handle);
|
||||
}
|
||||
|
||||
int actualSize() {
|
||||
/// Get the actual used size. See also [totalSize].
|
||||
int get actualSize {
|
||||
return _actualSize(_handle);
|
||||
}
|
||||
|
||||
@@ -375,6 +471,7 @@ class MMKV {
|
||||
free(keyPtr);
|
||||
}
|
||||
|
||||
/// See also [trim()].
|
||||
void removeValues(List<String> keys) {
|
||||
if (keys.isEmpty) {
|
||||
return;
|
||||
@@ -401,22 +498,36 @@ class MMKV {
|
||||
_clearAll(_handle);
|
||||
}
|
||||
|
||||
/// Synchronize memory to file.
|
||||
/// You don't need to call this, really, I mean it.
|
||||
/// Unless you worry about running out of battery.
|
||||
/// * Pass `true` to perform synchronous write.
|
||||
/// * Pass `false` to perform asynchronous write, return immediately.
|
||||
void sync(bool sync) {
|
||||
_mmkvSync(_handle, _bool2Int(sync));
|
||||
}
|
||||
|
||||
/// Clear all caches (on memory warning).
|
||||
void clearMemoryCache() {
|
||||
_clearMemoryCache(_handle);
|
||||
}
|
||||
|
||||
static int pageSize() {
|
||||
/// Get memory page size.
|
||||
static int get pageSize {
|
||||
return _pageSize();
|
||||
}
|
||||
|
||||
/// Trim the file size to minimal.
|
||||
///
|
||||
/// * MMKV's size won't reduce after deleting key-values.
|
||||
/// * Call this method after lots of deleting if you care about disk usage.
|
||||
/// * Note that [clearAll()] has the similar effect.
|
||||
void trim() {
|
||||
_trim(_handle);
|
||||
}
|
||||
|
||||
/// Close the instance when it's no longer needed in the near future.
|
||||
/// Any subsequent call to the instance is **undefined behavior**.
|
||||
void close() {
|
||||
_mmkvClose(_handle);
|
||||
}
|
||||
@@ -512,171 +623,203 @@ String _buffer2String(Pointer<Uint8> ptr, int length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final DynamicLibrary nativeLib = Platform.isAndroid
|
||||
final DynamicLibrary _nativeLib = Platform.isAndroid
|
||||
? DynamicLibrary.open("libmmkv.so")
|
||||
: DynamicLibrary.process();
|
||||
|
||||
final void Function(Pointer<Utf8> rootDir, int logLevel) _mmkvInitialize =
|
||||
Platform.isIOS ? null : nativeLib
|
||||
.lookup<NativeFunction<Void Function(Pointer<Utf8>, Int32)>>("mmkvInitialize")
|
||||
.asFunction();
|
||||
Platform.isIOS
|
||||
? null
|
||||
: _nativeLib
|
||||
.lookup<NativeFunction<Void Function(Pointer<Utf8>, Int32)>>(
|
||||
"mmkvInitialize")
|
||||
.asFunction();
|
||||
|
||||
final Pointer<Void> Function(Pointer<Utf8> mmapID, int, Pointer<Utf8> cryptKey, Pointer<Utf8> rootDir) _getMMKVWithID =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Pointer<Void> Function(Pointer<Utf8>, Uint32, Pointer<Utf8>, Pointer<Utf8>)>>("getMMKVWithID")
|
||||
.asFunction();
|
||||
final Pointer<Void> Function(Pointer<Utf8> mmapID, int, Pointer<Utf8> cryptKey,
|
||||
Pointer<Utf8> rootDir) _getMMKVWithID =
|
||||
_nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Pointer<Void> Function(Pointer<Utf8>, Uint32, Pointer<Utf8>,
|
||||
Pointer<Utf8>)>>("getMMKVWithID")
|
||||
.asFunction();
|
||||
|
||||
final Pointer<Void> Function(Pointer<Utf8> cryptKey) _getDefaultMMKV =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Pointer<Void> Function(Pointer<Utf8>)>>("getDefaultMMKV")
|
||||
.asFunction();
|
||||
_nativeLib
|
||||
.lookup<NativeFunction<Pointer<Void> Function(Pointer<Utf8>)>>(
|
||||
"getDefaultMMKV")
|
||||
.asFunction();
|
||||
|
||||
final Pointer<Utf8> Function(Pointer<Void>) _mmapID =
|
||||
nativeLib
|
||||
final Pointer<Utf8> Function(Pointer<Void>) _mmapID = _nativeLib
|
||||
.lookup<NativeFunction<Pointer<Utf8> Function(Pointer<Void>)>>("mmapID")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _encodeBool =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Int8 Function(Pointer<Void>, Pointer<Utf8>, Int8)>>("encodeBool")
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _encodeBool = _nativeLib
|
||||
.lookup<NativeFunction<Int8 Function(Pointer<Void>, Pointer<Utf8>, Int8)>>(
|
||||
"encodeBool")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _decodeBool =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Int8 Function(Pointer<Void>, Pointer<Utf8>, Int8)>>("decodeBool")
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _decodeBool = _nativeLib
|
||||
.lookup<NativeFunction<Int8 Function(Pointer<Void>, Pointer<Utf8>, Int8)>>(
|
||||
"decodeBool")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _encodeInt32 =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Int8 Function(Pointer<Void>, Pointer<Utf8>, Int32)>>("encodeInt32")
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _encodeInt32 = _nativeLib
|
||||
.lookup<NativeFunction<Int8 Function(Pointer<Void>, Pointer<Utf8>, Int32)>>(
|
||||
"encodeInt32")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _decodeInt32 =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Int32 Function(Pointer<Void>, Pointer<Utf8>, Int32)>>("decodeInt32")
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _decodeInt32 = _nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Int32 Function(Pointer<Void>, Pointer<Utf8>, Int32)>>("decodeInt32")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _encodeInt64 =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Int8 Function(Pointer<Void>, Pointer<Utf8>, Int64)>>("encodeInt64")
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _encodeInt64 = _nativeLib
|
||||
.lookup<NativeFunction<Int8 Function(Pointer<Void>, Pointer<Utf8>, Int64)>>(
|
||||
"encodeInt64")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _decodeInt64 =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Int64 Function(Pointer<Void>, Pointer<Utf8>, Int64)>>("decodeInt64")
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _decodeInt64 = _nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Int64 Function(Pointer<Void>, Pointer<Utf8>, Int64)>>("decodeInt64")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, double) _encodeDouble =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Int8 Function(Pointer<Void>, Pointer<Utf8>, Double)>>("encodeDouble")
|
||||
.asFunction();
|
||||
_nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Int8 Function(
|
||||
Pointer<Void>, Pointer<Utf8>, Double)>>("encodeDouble")
|
||||
.asFunction();
|
||||
|
||||
final double Function(Pointer<Void>, Pointer<Utf8>, double) _decodeDouble =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Double Function(Pointer<Void>, Pointer<Utf8>, Double)>>("decodeDouble")
|
||||
.asFunction();
|
||||
_nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Double Function(
|
||||
Pointer<Void>, Pointer<Utf8>, Double)>>("decodeDouble")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, Pointer<Uint8>, int) _encodeBytes =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Int8 Function(Pointer<Void>, Pointer<Utf8>, Pointer<Uint8>, Uint64)>>("encodeBytes")
|
||||
.asFunction();
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, Pointer<Uint8>, int)
|
||||
_encodeBytes = _nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Int8 Function(Pointer<Void>, Pointer<Utf8>, Pointer<Uint8>,
|
||||
Uint64)>>("encodeBytes")
|
||||
.asFunction();
|
||||
|
||||
final Pointer<Uint8> Function(Pointer<Void>, Pointer<Utf8>, Pointer<Uint64>) _decodeBytes =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Pointer<Uint8> Function(Pointer<Void>, Pointer<Utf8>, Pointer<Uint64>)>>("decodeBytes")
|
||||
.asFunction();
|
||||
final Pointer<Uint8> Function(Pointer<Void>, Pointer<Utf8>, Pointer<Uint64>)
|
||||
_decodeBytes = _nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Pointer<Uint8> Function(Pointer<Void>, Pointer<Utf8>,
|
||||
Pointer<Uint64>)>>("decodeBytes")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Uint8>, int) _reKey =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Int8 Function(Pointer<Void>, Pointer<Uint8>, Uint64)>>("reKey")
|
||||
final int Function(Pointer<Void>, Pointer<Uint8>, int) _reKey = _nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Int8 Function(Pointer<Void>, Pointer<Uint8>, Uint64)>>("reKey")
|
||||
.asFunction();
|
||||
|
||||
final Pointer<Uint8> Function(Pointer<Void>, Pointer<Uint64>) _cryptKey =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Pointer<Uint8> Function(Pointer<Void>, Pointer<Uint64>)>>("cryptKey")
|
||||
.asFunction();
|
||||
_nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Pointer<Uint8> Function(
|
||||
Pointer<Void>, Pointer<Uint64>)>>("cryptKey")
|
||||
.asFunction();
|
||||
|
||||
final void Function(Pointer<Void>, Pointer<Uint8>, int) _checkReSetCryptKey =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Void Function(Pointer<Void>, Pointer<Uint8>, Uint64)>>("checkReSetCryptKey")
|
||||
_nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Void Function(Pointer<Void>, Pointer<Uint8>,
|
||||
Uint64)>>("checkReSetCryptKey")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _valueSize = _nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Uint32 Function(Pointer<Void>, Pointer<Utf8>, Int8)>>("valueSize")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, int) _valueSize =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Uint32 Function(Pointer<Void>, Pointer<Utf8>, Int8)>>("valueSize")
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, Pointer<Void>, int)
|
||||
_writeValueToNB = _nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Int32 Function(Pointer<Void>, Pointer<Utf8>, Pointer<Void>,
|
||||
Uint32)>>("writeValueToNB")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Pointer<Pointer<Utf8>>>,
|
||||
Pointer<Pointer<Uint32>>) _allKeys =
|
||||
_nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Uint64 Function(Pointer<Void>, Pointer<Pointer<Pointer<Utf8>>>,
|
||||
Pointer<Pointer<Uint32>>)>>("allKeys")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>) _containsKey = _nativeLib
|
||||
.lookup<NativeFunction<Int8 Function(Pointer<Void>, Pointer<Utf8>)>>(
|
||||
"containsKey")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>, Pointer<Void>, int) _writeValueToNB =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Int32 Function(Pointer<Void>, Pointer<Utf8>, Pointer<Void>, Uint32)>>("writeValueToNB")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Pointer<Pointer<Utf8>>>, Pointer<Pointer<Uint32>>) _allKeys =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Uint64 Function(Pointer<Void>, Pointer<Pointer<Pointer<Utf8>>>, Pointer<Pointer<Uint32>>)>>("allKeys")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>, Pointer<Utf8>) _containsKey =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Int8 Function(Pointer<Void>, Pointer<Utf8>)>>("containsKey")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>) _count =
|
||||
nativeLib
|
||||
final int Function(Pointer<Void>) _count = _nativeLib
|
||||
.lookup<NativeFunction<Uint64 Function(Pointer<Void>)>>("count")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>) _totalSize =
|
||||
nativeLib
|
||||
final int Function(Pointer<Void>) _totalSize = _nativeLib
|
||||
.lookup<NativeFunction<Uint64 Function(Pointer<Void>)>>("totalSize")
|
||||
.asFunction();
|
||||
|
||||
final int Function(Pointer<Void>) _actualSize =
|
||||
nativeLib
|
||||
final int Function(Pointer<Void>) _actualSize = _nativeLib
|
||||
.lookup<NativeFunction<Uint64 Function(Pointer<Void>)>>("actualSize")
|
||||
.asFunction();
|
||||
|
||||
final void Function(Pointer<Void>, Pointer<Utf8>) _removeValueForKey =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Void Function(Pointer<Void>, Pointer<Utf8>)>>("removeValueForKey")
|
||||
.asFunction();
|
||||
_nativeLib
|
||||
.lookup<NativeFunction<Void Function(Pointer<Void>, Pointer<Utf8>)>>(
|
||||
"removeValueForKey")
|
||||
.asFunction();
|
||||
|
||||
final void Function(Pointer<Void>, Pointer<Pointer<Utf8>>, Pointer<Uint32>, int) _removeValuesForKeys =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Void Function(Pointer<Void>, Pointer<Pointer<Utf8>>, Pointer<Uint32>, Uint64)>>("removeValuesForKeys")
|
||||
.asFunction();
|
||||
final void Function(Pointer<Void>, Pointer<Pointer<Utf8>>, Pointer<Uint32>, int)
|
||||
_removeValuesForKeys = _nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Void Function(Pointer<Void>, Pointer<Pointer<Utf8>>,
|
||||
Pointer<Uint32>, Uint64)>>("removeValuesForKeys")
|
||||
.asFunction();
|
||||
|
||||
final void Function(Pointer<Void>) _clearAll =
|
||||
nativeLib
|
||||
final void Function(Pointer<Void>) _clearAll = _nativeLib
|
||||
.lookup<NativeFunction<Void Function(Pointer<Void>)>>("clearAll")
|
||||
.asFunction();
|
||||
|
||||
final void Function(Pointer<Void>, int) _mmkvSync =
|
||||
nativeLib
|
||||
final void Function(Pointer<Void>, int) _mmkvSync = _nativeLib
|
||||
.lookup<NativeFunction<Void Function(Pointer<Void>, Int8)>>("mmkvSync")
|
||||
.asFunction();
|
||||
|
||||
final void Function(Pointer<Void>) _clearMemoryCache =
|
||||
nativeLib
|
||||
final void Function(Pointer<Void>) _clearMemoryCache = _nativeLib
|
||||
.lookup<NativeFunction<Void Function(Pointer<Void>)>>("clearMemoryCache")
|
||||
.asFunction();
|
||||
|
||||
final int Function() _pageSize =
|
||||
nativeLib
|
||||
final int Function() _pageSize = _nativeLib
|
||||
.lookup<NativeFunction<Int32 Function()>>("pageSize")
|
||||
.asFunction();
|
||||
|
||||
final void Function(Pointer<Void>) _trim =
|
||||
nativeLib
|
||||
final void Function(Pointer<Void>) _trim = _nativeLib
|
||||
.lookup<NativeFunction<Void Function(Pointer<Void>)>>("trim")
|
||||
.asFunction();
|
||||
|
||||
final void Function(Pointer<Void>) _mmkvClose =
|
||||
nativeLib
|
||||
final void Function(Pointer<Void>) _mmkvClose = _nativeLib
|
||||
.lookup<NativeFunction<Void Function(Pointer<Void>)>>("mmkvClose")
|
||||
.asFunction();
|
||||
|
||||
final void Function(Pointer<Void>, Pointer<Void>, int) _memcpy =
|
||||
nativeLib
|
||||
.lookup<NativeFunction<Void Function(Pointer<Void>, Pointer<Void>, Uint64)>>("mmkvMemcpy")
|
||||
final void Function(Pointer<Void>, Pointer<Void>, int) _memcpy = _nativeLib
|
||||
.lookup<
|
||||
NativeFunction<
|
||||
Void Function(Pointer<Void>, Pointer<Void>, Uint64)>>("mmkvMemcpy")
|
||||
.asFunction();
|
||||
|
||||
Reference in New Issue
Block a user