20

I'm searching for a solution to combine freezed and hive packages. For example like that:

@freezed
abstract class Person extends HiveObject with _$Person {
  @HiveType(typeId: 0)
  factory Person({@HiveField(0) String name, @HiveField(1) int age}) = _Person;
}

I know that this is not possible out of the box, but I think you know what I want to achieve. What would be the best way to implement freezed with hive?

The only solution that I can currently think of is to store the json-String which is generated by freezed in hive. But I hope there is a better solution.

padaleiana
  • 955
  • 1
  • 14
  • 23
DennisSzymanski
  • 578
  • 4
  • 11
  • From the freezed documentation, `All decorators passed to a constructor parameter are "copy-pasted" to the generated property too.` So what makes you think your code wouldn't work out of the box? – Abion47 Feb 24 '20 at 22:22
  • 2
    You can't use freezed because `HiveObject` is mutable. See this: https://github.com/hivedb/hive/issues/225 – Frank Treacy Feb 24 '20 at 22:25
  • @FrankTreacy thanks for pointing this out to me ! :) I guess I could have searched better .. I only searched the freezed github for this topic – DennisSzymanski Feb 25 '20 at 05:47

3 Answers3

38

yes, it is now possible, make sure your min version is hive_generator: ^0.7.2+1.

as an example you could write:

import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hive/hive.dart';

part 'immutable_class.freezed.dart';
part 'immutable_class.g.dart';

@freezed
abstract class ImmutableClass with _$ImmutableClass {
  @HiveType(typeId: 5, adapterName: 'ImmutableClassAdapter')
  const factory ImmutableClass({
    @JsonKey(name: 'id', required: true, disallowNullValue: true) @HiveField(0) int id,
    @HiveField(1) int someField1,
    @HiveField(2) String someField2,
  }) = _ImmutableClass;

  factory ImmutableClass.fromJson(Map<String, dynamic> json) => _$ImmutableClassFromJson(json);
}

the only disadvantage is that you should specify the name of your adaptor.

update

in freezed: ^2.3.2 you can simply do the following

@freezed
abstract class ImmutableClass extends HiveObject with _$ImmutableClass {
  
  ImmutableClass._();

  @HiveType(typeId: 5)
  factory Person({@HiveField(1) int someField1, @HiveField(2) String someField2}) = _ImmutableClass;
}
mohammad
  • 2,568
  • 3
  • 20
  • 41
  • The adapter isn't automatically generated for me after running build_runner. Should it be? – squirtgun Jan 31 '22 at 20:48
  • @squirtgun I noticed this as well. It seems it is _not_ generated if you use `flutter pub run build_runner build --delete-conflicting-outputs` . If you run again with `flutter pub run build_runner build` it seems to work. – Shane Feb 18 '22 at 00:17
  • in hive_generator: ^2.0.0, it does not need adapterName. it is created automatically. – Jetwiz Feb 21 '23 at 16:40
  • If you're defining a [union type](https://pub.dev/packages/freezed#union-types-and-sealed-classes) should you have a different `@HiveType` `typeId` for each separate factory constructor? – dwb Mar 26 '23 at 14:37
1

Simple you can add a private constructor

@freezed
abstract class Person extends HiveObject with _$Person {
  
  Person._(); //Add this line

  @HiveType(typeId: 0)
  factory Person({@HiveField(0) String name, @HiveField(1) int age}) = _Person;
}
ijas
  • 409
  • 5
  • 8
0
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hive/hive.dart';
part 'person.freezed.dart';
part 'person.g.dart';

@Freezed()
@JsonSerializable()
class Person with _$Person {

    @HiveType(typeId: 30, adapterName: 'PersonAdapter')
    const factory Person({
        @JsonKey(name: 'name')
        @HiveField(0)
        required String name,
        @JsonKey(name: 'age')
        @HiveField(1)
        required int age,
      }) = _Person;
}
General Grievance
  • 4,555
  • 31
  • 31
  • 45