I'm using hive for locally caching.
In the application I have an I hive object named user.
class UserModel extends HiveObject implements Copyable<UserModel> {
UserModel({
required this.id,
required this.name,
});
@HiveField(0)
String id;
@HiveField(1)
String name;
factory UserModel.fromJson(Map<String,dynamic> json) => UserModel(
id: json['id'],
name: json['name']
);
}
class UserModelAdapter extends TypeAdapter<UserModel> {
@override
final typeId = 1;
@override
UserModel read(BinaryReader reader) {
var numOfFields = reader.readByte();
var fields = <int, dynamic>{
for (var i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return UserModel(
id: fields[0] as String,
name: fields[1] as String,
);
}
@override
void write (BinaryWriter writer, UserModel obj){
writer
..writeByte(2)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.name)
}
}
}
The above user model is a part of app that's now live and its working as expected. Now I wanted to add a new field named favorite and i have modified the userobject as follows
class UserModel extends HiveObject implements Copyable<UserModel> {
UserModel({
required this.id,
required this.name,
required this.favourite
});
@HiveField(0)
String id;
@HiveField(1)
String name;
@HiveField(2)
List<String> favourite
factory UserModel.fromJson(Map<String,dynamic> json) => UserModel(
id: json['id'],
name: json['name'],
favourite : List<String>.from(
json["favourite"] ?? [].map((x) => x))
);
}
class UserModelAdapter extends TypeAdapter<UserModel> {
@override
final typeId = 1;
@override
UserModel read(BinaryReader reader) {
var numOfFields = reader.readByte();
var fields = <int, dynamic>{
for (var i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return UserModel(
id: fields[0] as String,
name: fields[1] as String,
favourite: fields[2] as List<String>
);
}
@override
void write (BinaryWriter writer, UserModel obj){
writer
..writeByte(3)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.name)
..writeByte(2)
..write(obj.favourite)
}
}
}
However After updating the userobject as shown as above by adding new field the new version of the app breaks by throwing error from type adapter. How to ensure adding new fields wont break the app ?
I am not sure if this is useful to you after all this time, but for the new-comers to this question,
hive_generatorversion 1.1.0 and above lets you pass a named parameterdefaultValueto your@HiveFieldannotation.So, on newly created fields one can give a default value like the below:
This gives
someNewFieldthe value20if it is null from the cache as a first value.Custom Adapter
Or, as a second option, you can always create custom adapters for your hive models. This is a bit complex and cumbersome to do but if you came here for an answer, you probably need this kind of solution. This approach is also useful if the type of a field is changed (for some reason).
Assume this is your hive model:
and this is your generated
some_model.g.dartfile:If you want to add
someNewFieldto this class, you can customize the class and adapter like below:All there is left to do is to register
CustomSomeModelAdapterto hive: