🐰
【Flutter】ジェネリクスを活用してfreezedで生成されるファイル数を減らす
はじめに
Flutterの開発において広く利用されいてる、freezed
では、自分で作成したクラスを作るたびに自動生成のファイルが作成されます。
そのため、クラス数を増やすと自動生成されるファイル数も増え、プロジェクトのファイル数が多くなってしまうデメリットがあります。
そこで、ジェネリクスを使ってクラスを共通化してあげて、自動生成されるファイル数を抑える営みをしてみました。
TODO
今回は、Riverpodパターンにおける、Stateクラスを共通化してみたいと思います。
アーキテクチャについては、以下の記事がとても参考になりました。
ジェネリクスを使ったコード
例えば、APIを使って何らかのデータ(T
)を取得する処理がアプリ内で共通で使われるということであれば、以下のように共通化できそうです。
common_fetch_state.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'common_fetch_state.freezed.dart';
abstract class CommonFetchState<T> with _$CommonFetchState<T> {
const factory CommonFetchState({
(false) bool isLoading,
(null) T? result,
(null) Exception? error,
}) = _CommonFetchState<T>;
}
- API通信中はローディング状態を管理したいため、
isLoading
を定義 - APIから取得するデータはリクエストするAPIによって異なるので
result
はT
で定義 - 通信エラーなどの例外が発生した場合に備えて、
error
を定義
こうしてあげれば、「ユーザー情報」「お知らせ」「投稿一覧」などあらゆるデータの取得処理を1つのStateだけで管理することができます。
今回は、APIによる取得処理を例に挙げましたが、この辺は共通化したいユースケースによってState
の中身を変更できると思います。
使ってみる
使う時はCommonFetchState<HogeModel>
のようにしてT
となっているところに任意のModel
を入れてあげれば、result
の型が決まるので、取得したい値に応じて処理を書いてあげることができます。
hoge_notifier.dart
// StateProvider
final hogeStateProvider =
StateNotifierProvider.autoDispose<HogeNotifier, CommonFetchState<HogeModel>>(
(_) => HogeNotifier(),
);
// Model
class HogeModel {
HogeModel({required this.hoge});
final String hoge;
}
// Notifier
class HogeNotifier extends StateNotifier<CommonFetchState<HogeModel>> {
HogeNotifier({CommonFetchState<HogeModel>? initialState})
: super(initialState ?? const CommonFetchState<HogeModel>());
Future<void> fetch() async {
state = state.copyWith(isLoading: true, result: HogeModel(hoge: ''), error: null);
Future.delayed(const Duration(seconds: 1));
state = state.copyWith(isLoading: false, result: HogeModel(hoge: 'hoge'), error: null);
}
}
Discussion