dartpub.dev DartNative · beta
plugins / senzer_mmkv
se

senzer_mmkv

v1.0.2 MIT

Ultra-fast, synchronous, C++-backed MMKV key-value storage for DartNative.

senzer_mmkv is an ultra-fast, synchronous key-value storage library for DartNative, backed directly by C++ MMKV through FFI. It supports primitives, binary data, strongly typed models and collections, plus native prefix/suffix key filtering designed to minimize allocations and marshaling overhead. It also includes AES-128/256 encryption, multi-process synchronization, real-time change listeners, and storage management for iOS 15+ and Android API 23+.

by pigeonmal/senzer_mmkv · DartNative ≥ 3.0 · updated today
Install
Free
pubspec.yaml
dependencies:
  senzer_mmkv:
    hosted: https://dartpub.dev
    version: ^1.0.2
Weekly installs
0
Active apps
0
Rating
0.0 · 0
Open issues
0

senzer_mmkv

Ultra-fast, synchronous, C++-backed MMKV key-value storage for DartNative.

  • Synchronous & Zero-Copy: Direct C++ FFI bindings with borrowed native buffer decoding.
  • Native Key Filtering: In-engine C++ prefix and suffix filtering (getAllKeys(prefix: ..., suffix: ...)) with zero heap allocations.
  • Rich Types: Primitives (String, bool, int, double, Uint8List) and strongly typed custom models.
  • Battle-Tested: Multi-process support, AES-128 / AES-256 encryption, and real-time change listeners.
  • Platforms: iOS 15+ and Android API 23+.

Showcase


Installation

Add senzer_mmkv to your pubspec.yaml:

dependencies:
  senzer_mmkv: ^1.0.2

dev_dependencies:
  senzer_mmkv_generator: ^1.0.2

Then run dn pub get. Before creating your first widget, ensure DartNative plugins are registered:

DartNativePluginRegistrant.registerAll();

Quick Start

import 'dart:typed_data';
import 'package:senzer_mmkv/senzer_mmkv.dart';

void main() {
  // 1. Create or open an MMKV instance
  final storage = createMMKV(id: 'app_settings');

  // 2. Write primitive values
  storage.set('theme', 'dark');
  storage.set('notifications_enabled', true);
  storage.setInt('launch_count', 42);
  storage.setDouble('version', 2.1);
  storage.set('auth_token', Uint8List.fromList([0xDE, 0xAD, 0xBE, 0xEF]));

  // 3. Read values synchronously
  final theme = storage.getString('theme'); // 'dark'
  final isEnabled = storage.getBoolean('notifications_enabled') ?? false;
  final launchCount = storage.getInt('launch_count') ?? 0;
  final token = storage.getBuffer('auth_token');

  // 4. Inspect or clean up
  if (storage.contains('theme')) {
    storage.remove('theme');
  }

  // Close when finished (optional)
  storage.close();
}

Typed Models and Collections

Use senzer_mmkv_generator to store complex models, nested structures, lists, and maps without manual JSON parsing or reflection:

1. Define your model

import 'package:senzer_mmkv/senzer_mmkv.dart';

@MMKVModel()
final class UserProfile {
  const UserProfile({
    required this.id,
    required this.name,
    this.email,
    this.role = 'user',
  });

  final int id;
  final String name;
  final String? email;
  final String role;
}

2. Generate codecs

dart run senzer_mmkv_generator:mmkv_generate .

3. Register and use

import 'mmkv_codecs.g.dart';

void main() {
  // Register generated codecs once at app startup
  registerMMKVGeneratedCodecs();

  final storage = createMMKV(id: 'users');

  final user = UserProfile(id: 1, name: 'Alex', email: '[email protected]');

  // Store and read single objects
  storage.setObject<UserProfile>('current_user', user);
  final restoredUser = storage.getObject<UserProfile>('current_user');

  // Store and read typed lists
  storage.setList<UserProfile>('team', [user]);
  final team = storage.getList<UserProfile>('team');

  // Store and read typed sets
  storage.setSet<String>('user_tags', {'admin', 'tester'});
  final tags = storage.getSet<String>('user_tags');

  // Store and read typed maps
  storage.setMap<String, UserProfile>('users_by_id', {'u1': user});
  final usersMap = storage.getMap<String, UserProfile>('users_by_id');
}

Advanced Features

Encryption (AES-128 & AES-256)

Protect sensitive data using hardware-accelerated encryption:

final secureStorage = createMMKV(
  id: 'secure_vault',
  encryptionKey: 'your-32-byte-secret-key-for-aes256',
  encryptionType: MMKVEncryptionType.aes256,
);

// Encrypt an existing unencrypted store:
secureStorage.encrypt('your-32-byte-secret-key-for-aes256', encryptionType: MMKVEncryptionType.aes256);

// Decrypt back to plaintext if desired:
secureStorage.decrypt();

Multi-Process Support

Synchronize state across multiple processes or app extensions:

final sharedStorage = createMMKV(
  id: 'shared_data',
  mode: MMKVMode.multiProcess,
);

// Check and sync when external processes write updates:
sharedStorage.checkContentChanged();

Value Change Listeners

Listen to key changes in real time:

final unsubscribe = storage.addOnValueChangedListener((key) {
  print('Key updated: $key');
});

// Remove listener when no longer needed:
unsubscribe();
  • Zero Heap Allocations: Matching keys are evaluated and packed directly in C++ via memcmp. Non-matching keys are discarded immediately, avoiding Dart String allocations and FFI marshaling overhead.
  • Overlapping Match Support: Prefixes and suffixes can safely overlap without length truncation.

Memory & Storage Management

// Compact the disk file to reclaim unused space
storage.trim();

// Free native memory cache (useful upon receiving low-memory warnings)
storage.clearMemoryCache();

// Delete all keys in this instance
storage.clearAll();

// Delete the MMKV instance file completely from disk
deleteMMKV('app_settings');

// Combined prefix and suffix
storage.getAllKeys(prefix: 'users:', suffix: ':profile');

API Reference

Method Description
set(key, value) Stores String, bool, int, double, or Uint8List
getString(key) Reads a UTF-8 string
getBoolean(key) Reads a boolean value
getNumber(key) / getDouble(key) Reads a 64-bit IEEE-754 floating point number
getInt(key) / getInt64(key) Reads an exact 64-bit signed integer
getBuffer(key) Reads raw binary data into a Uint8List
setObject<T>(key, value) Serializes a typed @MMKVModel
getObject<T>(key) Deserializes a typed @MMKVModel
setList<T>(key, list) Serializes a typed list of models or primitives
getList<T>(key) Deserializes a typed list
setSet<T>(key, set) Serializes a typed set of models or primitives
getSet<T>(key) Deserializes a typed set
setMap<K, V>(key, map) Serializes a typed map
getMap<K, V>(key) Deserializes a typed map
contains(key) Checks if a key exists
getAllKeys({prefix, suffix}) Returns stored keys, optionally filtered natively in C++ by prefix and/or suffix
length Number of stored keys
byteSize Actual storage footprint on disk in bytes
remove(key) Deletes a key-value pair
clearAll() Wipes all entries in the instance
trim() Compacts the underlying memory-mapped file
clearMemoryCache() Frees in-memory cached structures
close() Closes the local instance handle
existsMMKV(id) Checks whether an MMKV database exists on disk
deleteMMKV(id) Permanently deletes an MMKV database file from disk

License

MIT License. See LICENSE and Third Party Notices.