Simplify custom type registration
partially hide typeid for registration
The bottom line is that the id is initialized only once and cannot be changed in the future. it would be more logical to combine it with the model itself
now:
// model
@HiveType()
class User extends HiveObject {
User({
@required this.id,
@required this.email,
});
static const int typeId = 1;
int id;
String email;
}
// adapter
class UserAdapter extends TypeAdapter<User> {
@override
User read(BinaryReader reader) {
var numOfFields = reader.readByte();
var fields = <int, dynamic>{
for (var i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return User();
}
@override
void write(BinaryWriter writer, User obj) {
writer..writeByte(0);
}
}
// registration
Hive.registerAdapter(UserAdapter(), User.typeId)
After:
// model
@HiveType(typeId: 1)
class User extends HiveObject {
User({
@required this.id,
@required this.email,
});
int id;
String email;
}
// adapter
class UserAdapter extends TypeAdapter<User> {
@override
int get typeId => 1;
@override
User read(BinaryReader reader) {
var numOfFields = reader.readByte();
var fields = <int, dynamic>{
for (var i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return User();
}
@override
void write(BinaryWriter writer, User obj) {
writer..writeByte(0);
}
}
// registration
Hive.registerAdapter(UserAdapter())
I think this is a great idea. Thank you for the pull requests. Please give me a few days to merge them :)
Published with v1.3.0.
With this implement, I have something to say...
Once we moved typeId to annotation, it just makes the id management gets harder and chaos. Before I can wrote code like this:
int adapterIndex = 0;
Hive.registerAdapter(SomeAdapter(), adapterIndex++);
Hive.registerAdapter(AnotherAdapter(), adapterIndex++);
That makes the typeId completely auto increased with more and more adapter added. Same as when we are trying to add field (HiveField) in a HiveType. Users SHOULD NOT modify the sequence once adapters were registered.
The new change might made the typeId consist, but when there're ten or hundreds of HiveType need to be added, it required the project itself to build something like Map<Type, int> to find the actual typeId.
Too aggressive with this change, and it didn't land on a new major version. 馃槩
I would not recommend the way you registered TypeAdapters in the past. You already mentioned the first problem, you are not allowed to change the order. But how would you remove a type? It gets quite messy.
I'm thinking about a way to automate the typeId and fieldId management but it will take time.
Too aggressive with this change, and it didn't land on a new major version.
I'm sorry for that. I should have created a new major version.
Ultimately I think the new API is easier to use and more consistent. I also don't think it is a good idea to determine typeIds at runtime. They should be under version control.
I would not recommend the way you registered
TypeAdaptersin the past. You already mentioned the first problem, you are not allowed to change the order. But how would you remove a type? It gets quite messy.
Actually when it comes to the app which was published, there's almost no chances to remove a type adapter or even a box.
I'm thinking about a way to automate the
typeIdandfieldIdmanagement but it will take time.
Maybe it just needs a box to store the ids :P (just kidding)
Now I'm using a class and constants to define typeIds, add or remove a type adapter will me more controllable and visualized:
@HiveType(typeId: HiveAdapterTypeIds.adapterA)
class A {}
class HiveAdapterTypeIds {
static const int adapterA = 0;
static const int adapterB = 1;
}
Generate constants was usually used to generate routes, I think at here it works.
Now I'm using a class and constants to define
typeIds, add or remove a type adapter will me more controllable and visualized:
Great idea!!! Does the generator accept the constants? I might recommend that in the docs...
Great idea!!! Does the generator accept the constants? I might recommend that in the docs...
Yes it works fine now. I've just finished reconfigure my projects with this migration. 馃槃
Sorry for not realizing this sooner, but this kind of broke my workflow.
In a project, I have some Entity classes, each of which has an Id<Entity>, which is just a typed wrapper class around a String. For example, NewsArticles would have an Id<NewsArticle>, Users an Id<User> and so on.
Because Hive doesn't support generics yet (writing an Id<User> with the auto-generated adapter and retrieving it returns an Id<dynamic>), I wrote a generic IdApater an then registered adapters for all the id types I use, like this:
class IdAdapter<T> extends TypeAdapter<Id<T>> {
@override
Id<T> read(BinaryReader reader) => Id<T>(reader.readString());
@override
void write(BinaryWriter writer, Id obj) => writer.writeString(obj.id);
}
class ColorAdapter extends TypeAdapter<Color> {
@override
Color read(BinaryReader reader) => Color(reader.readInt());
@override
void write(BinaryWriter writer, Color color) => writer.writeInt(color.value);
}
Hive
// this is an excerpt of the registry process
..registerAdapter(IdAdapter<ContentType>(), 41)
..registerAdapter(IdAdapter<Content>(), 42)
..registerAdapter(IdAdapter<Course>(), 43)
..registerAdapter(IdAdapter<Lesson>(), 44)
This doesn't work anymore with this feature implemented.
You could do the following:
class IdAdapter<T> extends TypeAdapter<Id<T>> {
@override
final int typeId;
IdAdapter(this.typeId);
...
}
Hive.registerAdapter(IdAdapter<ContentType>(41));
...
Works for us this way, thanks 馃槉
For the future though, I would strongly advise against pushing breaking changes in minor versions. This goes against the principles of semantic versioning: Versions of the form MAJOR.MINOR.PATCH should only contain breaking changes in major releases, although @Deprecated annotations may be added in minor releases.
Because the pub package manager heavily relies on semantic versioning, builds may break. For example, for apps relying on hive: ^1.2.1 (which is equivalent to hive: '>= 1.2.1 < 2.0.0'), builds may succeed on the local machine if no pub get was run for some time, but builds fail on the server CI because the newest version of Hive is chosen.
Most helpful comment
With this implement, I have something to say...
Once we moved
typeIdto annotation, it just makes theidmanagement gets harder and chaos. Before I can wrote code like this:That makes the
typeIdcompletely auto increased with more and more adapter added. Same as when we are trying to add field (HiveField) in aHiveType. Users SHOULD NOT modify the sequence once adapters were registered.The new change might made the
typeIdconsist, but when there're ten or hundreds ofHiveTypeneed to be added, it required the project itself to build something likeMap<Type, int>to find the actualtypeId.Too aggressive with this change, and it didn't land on a new major version. 馃槩