senzer_mmkv_generator
Analyzer-based source generator for senzer_mmkv typed binary codecs.
- Zero-Allocation Decoding: Decodes directly from borrowed native buffers.
- Schema Evolution: Stable numeric field IDs, safe renames, and backward compatibility.
- Enums & Collections: Full support for enums, lists, and maps of nested models.
- Watch Mode: Instant regeneration on save during development with hot reload.
Installation
Add as a development dependency:
dev_dependencies:
senzer_mmkv_generator: ^1.0.2
Usage
Run once
dart run senzer_mmkv_generator:mmkv_generate .
Watch mode (Recommended during development)
Keep the generator running in the background. It watches your files, debounces rapid edits, and regenerates on save:
dart run senzer_mmkv_generator:mmkv_generate --watch
The generator produces:
lib/mmkv_codecs.g.dart: Generated codecs andregisterMMKVGeneratedCodecs().lib/mmkv_schema.txt: Deterministic schema history tracking field IDs. Commit both files to Git.
Defining Models
Models must be final classes with final public fields and a single const unnamed constructor using this.field formals:
import 'package:senzer_mmkv/senzer_mmkv.dart';
@MMKVModel()
final class Address {
const Address({required this.city, required this.country});
final String city;
final String country;
}
@MMKVModel()
final class UserProfile {
const UserProfile({
required this.id,
required this.name,
this.email,
this.tags = const [],
this.address,
});
final int id;
final String name;
final String? email;
final List<String> tags;
final Address? address;
}
Supported Types
- Primitives & Scalars:
bool,int,double,String,Uint8List,DateTime,Duration,Uri,BigInt - Enums (annotated or referenced)
- Generated
@MMKVModelclasses - Nullable variations (
T?) - Typed collections:
List<T>,Set<T>,Map<K, V>
Enums
Enums are supported either directly with @MMKVModel() or by referencing any public enum in your models:
@MMKVModel()
enum UserStatus { active, pending, suspended }
Enums serialize as compact varints using their .index without heap allocations.
Schema Evolution & @MMKVField
Renaming fields without losing data
When renaming a variable in Dart, use @MMKVField(from: 'oldName'). The generator transfers the previous schema ID to the new field name so existing stored records decode seamlessly:
@MMKVModel()
final class UserProfile {
const UserProfile({
required this.displayName,
});
// Preserves existing data stored under 'name':
@MMKVField(from: 'name')
final String displayName;
}
Explicit numeric IDs
If you prefer explicit protobuf-style field IDs:
@MMKVModel()
final class UserProfile {
const UserProfile({
required this.id,
this.bio,
});
@MMKVField(id: 1)
final int id;
@MMKVField(id: 2)
final String? bio;
}
Adding new fields safely
When adding fields to models already used in production:
- Make it nullable (
final String? bio;) — older stored records without this field decode asnull. - Or provide a default value (
this.role = 'user';) — older stored records decode using the default value.
Runtime Registration
Call registerMMKVGeneratedCodecs() once at app launch before reading or writing typed models:
import 'package:senzer_mmkv/senzer_mmkv.dart';
import 'mmkv_codecs.g.dart';
void main() {
registerMMKVGeneratedCodecs();
final storage = createMMKV(id: 'data');
storage.setObject<UserProfile>('user', user);
}
[!NOTE] Codec registration is idempotent and safe across Flutter / DartNative hot reloads.