【Flutter】Entityクラスをfreezedで実装した

カテゴリー:Flutter投稿日:2024-02-04

riverpodやNavigation2.0が難しすぎてfreezedもちょっと敬遠していたけどすご簡単で使いやすかったのでメモ。

freezed使用前

class Task {
  int? id;
  String title;
  String? description;
  bool isComplete;
  int point;
  TaskType taskType;
  DateTime? atComplete;

  Task({
    this.id,
    required this.title,
    this.description,
    required this.isComplete,
    required this.point,
    required this.taskType,
    this.atComplete,
  });

  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'title': title,
      'description': description,
      'isComplete': isComplete ? 1 : 0,
      'point': point,
      'taskType': taskType.index,
      'atComplete': atComplete?.toIso8601String(),
    };
  }

  factory Task.fromMap(Map<String, dynamic> map) {
    return Task(
      id: map['id'] as int?,
      title: map['title'] as String,
      description: map['description'] as String?,
      isComplete: map['isComplete'] == 1,
      point: map['point'] as int,
      taskType: TaskType.values[map['taskType'] as int],
      atComplete: map['atComplete'] == null
          ? null
          : DateTime.parse(map['atComplete'] as String),
    );
  }
}

freezed使用後

part "task.freezed.dart";
part "task.g.dart";

@freezed
class Task with _$Task {
  const factory Task({
    int? id,
    required String title,
    String? description,
    @BoolIntConverter() @Default(false) bool isComplete,
    required int point,
    @TaskTypeConverter() required TaskType taskType,
    DateTime? atComplete,
  }) = _Task;

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

圧倒的省エネ。やることもpartを使って自動生成されるコードの指定。@freezedをつけるぐらい。enumとかで(デ)シリアライズに特有の処理をしたかったらconverterを実装するだけ。そのconverterも実装はすごい簡単。

class TaskTypeConverter implements JsonConverter<TaskType, int> {
  const TaskTypeConverter();

  @override
  TaskType fromJson(int json) {
    return TaskType.values[json];
  }

  @override
  int toJson(TaskType object) {
    return object.index;
  }
}

class BoolIntConverter implements JsonConverter<bool, int> {
  const BoolIntConverter();

  @override
  bool fromJson(int json) {
    return json == 1;
  }

  @override
  int toJson(bool object) {
    return object ? 1 : 0;
  }
}

最初にriverpodやNavigationに手を出していたせいでfreezedもややこしそうとか思っていたけどなんのことはなく超シンプル。導入していなかった自分を殴りたいぐらい。Flutterでプロジェクト作る時はとりあえず入れとけばいいんじゃないかな?