Flutter freezed のチートシート、もとい、知っている人向けのメモ
分かっている人(というか自分)向けのメモです。LiveTemplateなども記載した詳細な記事も作成しましたので、初めての方はそちらをご覧下さい。
インストール
ターミナルで実行する。ただし、5行をまとめて実行できない。1行ずつ実行する。
flutter pub add freezed_annotation
flutter pub add build_runner --dev
flutter pub add freezed --dev
flutter pub add json_serializable --dev
flutter pub add json_annotation
作成するクラス
ソーステンプレート
templateとTemplateを、自分の作成するクラスに合わせて修正する。
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';
part 'template.freezed.dart';
part 'template.g.dart';
@freezed
class Template with _$Template {
const factory Template({
required String title,
}) = _Template;
factory Template.fromJson(Map<String, dynamic> json) =>
_$TemplateFromJson(json);
}
実例と解説
@freezed
class Template with _$Template {
@Assert('(questions == null) != (asinQuestions == null)',
'questionsとasinQuestionsはどちらかは設定する必要がある')
const factory Template({
// requiedか?をつける
required String title,
String? comment,
// デフォルト値の設定
@Default(0) int questionLength,
// ListもMapも読み込める。素晴らしい!
List<String>? questions,
List<String>? asinQuestions,
// オブジェクトもJson読込が定義されていれば、入れられる
required Map<String, ResultInfoData> resultInfo,
}) = _WorkbookData;
}
Assert
作成されたデータの条件を定義できる。
第一引数の式が展開される。ただの文字列のため、build時にエラーが発生する。
(questions == null) != (asinQuestions == null)
というのは、questionsとasinQuestiosがnullか確認している。二つの回答が異なる場合、trueとfaluseだった場合、「!=」が成立する。つまり、片方が入力されているときのみ有効になる。両方値が入ったり、両方nullだった場合はエラーになる。
コード生成
・通常のコード生成
flutter pub run build_runner build
・コードの生成(強制)
flutter pub run build_runner build --delete-conflicting-outputs
・変更を監視してコード生成(ファイルを保存したら、自動でbuildされる)
flutter pub run build_runner watch
Jsonの読み書き
リストでないJsonの読込
var file = File('assets/data.json');
WorkboodData workboodData =
WorkbookData.fromJson(json.decode(file.readAsStringSync()));
リストのJsonの読込
var file = File('assets/list.json');
List<dynamic> jsonData = json.decode(file.readAsStringSync());
List<OverviewData> overviewData =
jsonData.map((data) => OverviewData.fromJson(data)).toList();
以下のようにまとめて書いたら、エラーになった。
json.decode(file.readAsStringSync()).map((data) => OverviewData.fromJson(data)).toList();
Jsonの書込
var output = File('test/result/test.json');
output.writeAsStringSync(json.encode(copy));
注意点
メンバー変数のうち、
intやString、freezedで生成したクラスは変更できないが、
ListとMapは変更できる。
// List
expect(copy.asinQuestions!.length, 95);
copy.asinQuestions!.removeLast();
expect(copy.asinQuestions!.length, 94);
// Map
expect(copy.resultInfo!.length, 4);
expect(copy.resultInfo.remove('rankA'), isNotNull);
expect(copy.resultInfo!.length, 3);
json_serializerとの比較
freezedの方が良いと考える
良い点
classの中で変数名を1回しか書かなくて良い
→json_serializerの場合、変数の定義とコンストラクタの定義で2回書く
悪い点
json変換を書いたとき、ファイルが2つ生成され、クラスファイルが3つになる
→son_serializerの場合、ファイルが1つ生成され、クラスファイルが2つ
単にテストを作りながら作ったから、快適だっただけかも、、
やらかしたエラーの履歴
type 'Null' is not a subtype of type 'Map<String, dynamic>' in type cast
fromJson実施時に、クラスの変数名とjsonの要素名が異なっていた。
You are missing a required dependency on json_annotation in the "dependencies" section of your pubspec with a lower bound of at least "4.3.0".
flutter pub add json_annotation
を実施したら解決した。以前はjson_annotationのプラグインがなくても実施できたけど、なんか変わったかな。
より詳しく学習するために
freezedはよくriverpodと一緒に使われます。riverpodも学習したい!という場合は、以下のUdemy講座をご利用ください。riverpodの基本から、MVVMモデルへの応用、もちろん、WebAPIやFirestoreからのデータも取り扱っています。ぜひご受講ください。
クーポンコードもありますので、ご利用ください。
Flutter x Riverpod x MVVMで実現するシンプルな設計
Discussion