見出し画像

freezed パッケージの使い方【Flutter/Dart】

Dart の freezed パッケージの使い方をすぐに理解できなかったのでまとめておきます。
freezed は Dart において、immutable なオブジェクト用のコード生成ができるパッケージです。

1. pubspec.yaml にインストール

pubspec.yaml に、パッケージを追加してインストールします。freezed は開発用のパッケージのため、dev_dependencies に追加します。build_runner も同様です。freezed_annnotation はその名の通り、@freezed 用のパッケージです。

# pubspec.yaml
dependencies:
 freezed_annotation:

dev_dependencies:
 build_runner:
 freezed:

2. クラスを作る

さて、freezed で生成するクラスを作成してみましょう。
この時点ではまだコードにエラーが出ますが無視して大丈夫です。
続くステップでコードが生成されると、エラーは消えます。
ここでは user.dart ファイルに User というクラスを定義してみましょう。 part 'user.freezed.dart'; の一行が必要です。これは、コード生成コマンドを実行すると user.freezed.dart という名前のファイルが同階層のフォルダに生成されて、それを同じライブラリとして扱いますよ、ということを意味します。foundation パッケージのインポートは必須ではないですが、追加すると devtool で綺麗に表示されるようです。
@freezed 以下はいろいろなバリエーションがありますが、ここでは名前付きコンストラクタとして定義しています。(詳しくシンタックスを知りたい方はこちら:https://pub.dev/packages/freezed#the-syntax)。
基本的な部分としては、_$User クラスを mixin することと、_User クラスをコンストラクタに代入する必要があります。これらのクラスがこれから生成されるクラスです。

// user.dart
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';

part 'user.freezed.dart';

@freezed
abstract class User with _$User {
 const factory User({String name, int age}) = _User;
}

3. Generator を走らせる

ターミナルで以下のコマンドを実行すると自動的に @freezed を見つけ出して、コードを生成してくれます。user.freezed.dart が生成されたと思います。コードに freezed 以外のエラーがある場合はうまくいきません。

flutter pub run build_runner build --delete-conflicting-outputs

4. 使ってみる

さて、コード生成がうまく行ったのか試してみましょう。

void main() {
   final user = User(name: 'katsuo', age: 12);
   final user2 = user.copyWith(age: 24)
}

Warning を無視する

生成されたコードは綺麗ではないため、Warning で注意されます。無視するには、ルートレベルに analysis_options.yaml を追加して以下を記述します。

# analysis_options.yaml
analyzer:
 exclude:
   - "**/*.g.dart"
   - "**/*.freezed.dart"


toJson / fromJson を定義する

toJson と fromJson が必要な場面は結構多いですが、それも簡単に実装してくれます。実装方法は、part 'user.g.dart';  の一行と、
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
の一行を追加するだけです。実際使うときは User を任意のクラス名に変換してください。

// user.dart
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';

part 'user.freezed.dart';
part 'user.g.dart';

@freezed
abstract class User with _$User {
 const factory User({String name, int age}) = _User;
 factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}

toJson/fromJson から外して欲しい変数がある場合には、@JsonKey(ignore: true) をつけてあげれば OK です。

また、変数ごとに独自の toJson / fromJson を設定することもできます。
それには、@JsonKey(fromJson: Function, toJson: Function) のように、関数を指定すればできちゃいます。この辺の機能は、json_serializableの機能です(freezed の内部で json_serializable を使っています)。

終わりに

freezed 便利ですね〜。Dart の公式でこういう機能を提供して欲しい。
今回はめちゃめちゃ基本的なところでしたが、気が向いたら詳細なシンタックスの説明を追記していきたいです。



この記事が気に入ったらサポートをしてみませんか?