メインコンテンツまでスキップ

Flutter - Freezed

参考資料

なんのために使うか

  • Dart では多くのオブジェクトが immutable であり、多くの利点がある。
  • その反面、mutable なオブジェクトを扱うのは大変。その大変さを軽減するためのライブラリである。

何ができるか

  • アサーション
  • デフォルト値の設定
  • 遅延初期化
  • deprecated の指定
  • toString
  • hashCode
  • ==(すべてのプロパティが等しいか)
  • CopyWith(既存オブジェクトの一部のプロパティのみを変更して新しく作成)
  • FromJson/ToJson

インストール

# pubspec.yaml
dependencies:
# freezedのアノテーションを利用可能にする
freezed_annotation:

dev_dependencies:
# コードジェネレータのランナー
build_runner:
# コードジェネレータ
freezed:

使い方

// main.dart

// パッケージのインポート
import 'package:flutter/foundation.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

// 自動生成されるコードを読み込む
part 'main.freezed.dart';

// モデルの宣言(_$Personと_Personは後で自動生成されるクラスのこと)
class Person with _$Person {
factory Person({
String? name,
int? age,
}) = _Person;
}

// 使うとき
var person = Person(name: 'Remi', age: 24);
print(person.name); // Remi
print(person.age); // 24

コードの自動生成方法

flutter pub run build_runner build

機能

アサーション

abstract class Person with _$Person {
@Assert('name.isNotEmpty', 'name cannot be empty')
@Assert('age >= 0')
factory Person({
String? name,
int? age,
}) = _Person;
}

デフォルト値

class Person with _$Person {
factory Person({
@Default("") String? name,
@Default(18) int? age,
}) = _Person;
}

deprecated

@freezed
class Person with _$Person {
const factory Person({
String? name,
int? age,
@deprecated Gender? gender,
}) = _Person;
}

toString

print(Person(name: 'Remi', age: 24)); // Person(name: Remi, age: 24)

==

print(
Person(name: 'Remi', age: 24) == Person(name: 'Remi', age: 24),
); // true

copyWith

var person = Person('Remi', 24);

// `age` not passed, its value is preserved
print(person.copyWith(name: 'Dash')); // Person(name: Dash, age: 24)

// `age` is set to `null`
print(person.copyWith(age: null)); // Person(name: Remi, age: null)

deepCopy もできる。詳細はこちらを参照。

FromJson/ToJson

  • json_serializableと適合するようにできる。
  • そのためには以下の2つの追記が必要。
    • part 'model.g.dart';
    • factory Model.fromJson(Map<String, dynamic> json) => _$ModelFromJson(json);
import 'package:freezed_annotation/freezed_annotation.dart';

part 'person.freezed.dart';
part 'person.g.dart';

@freezed
class Person with _$Person {
const factory Person({
String? name,
int? age,
@deprecated Gender? gender,
}) = _Person;

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