Skip to content

Using subtypes in boxes #893

Closed
Closed
@juleshyacinthe

Description

Question
I have a class User which is inherited by another class UserA. I have another class Order that uses UserA in different properties. When I put orders in a Hive box, everything looks ok. However, after a restart, UserA objects are always parsed as User objects, and when I try to get orders from my box I get an error in the Order reader. I don't really understand why and didn't find a solution browsing this repo's issues. The generated adapters look good to me, but I may be missing something.
The error I get is type 'User' is not a subtype of type 'UserA' in type cast.

Code sample

@HiveType(typeId: 0)
class User extends HiveObject {
  @HiveField(0)
  final String id;
  @HiveField(2)
  String firstName;
  @HiveField(3)
  String lastName;
  ...
}

@HiveType(typeId: 1)
class UserA extends User {
  @HiveField(4)
  String phoneNumber;
...
}

@HiveType(typeId: 3)
class Order extends ChangeNotifier implements Comparable<Order> {
 @HiveField(0)
  final String id;
  ...
  @HiveField(16)
  final UserA by;
  ...
}

class UserAdapter extends TypeAdapter<User> {
  @override
  final int typeId = 0;

  @override
  User read(BinaryReader reader) {
    final numOfFields = reader.readByte();
    final fields = <int, dynamic>{
      for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
    };
    return User(
      id: fields[0] as String,
      firstName: fields[2] as String,
      lastName: fields[3] as String,
    );
  }
...
}

class UserAAdapter extends TypeAdapter<UserA> {
  @override
  final int typeId = 1;

  @override
  UserA read(BinaryReader reader) {
    final numOfFields = reader.readByte();
    final fields = <int, dynamic>{
      for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
    };
    return UserA(
      id: fields[0] as dynamic,
      firstName: fields[2] as dynamic,
      lastName: fields[3] as dynamic,
      phoneNumber: fields[4] as dynamic,
    );
  }
...
}

class OrderAdapter extends TypeAdapter<Order> {
  @override
  final int typeId = 3;

  @override
  Order read(BinaryReader reader) {
    final numOfFields = reader.readByte();
    final fields = <int, dynamic>{
      for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
    };
    return Order(
      fields[0] as String,
      ...
      by: fields[16] as UserA,
      ...
    );
  }
...
}

// Adapter registration is done in this order:
initHive() async {
  await Hive.initFlutter();
  Hive
    ..registerAdapter<User>(UserAdapter())
    ..registerAdapter<UserA>(UserAAdapter())
    ..registerAdapter<Order>(OrderAdapter());
}

Version

  • Platform: iPhone SE 2020 (iOS 15.3)
  • Flutter version: 2.8.1
  • Hive version: 2.0.5

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions