【Flutter/Dart/Riverpod】familyメソッドの使い方!Providerに引数を渡す

この記事からわかること
- Flutter/Dartで状態管理を行うRiverpodとは?
- familyメソッドの使い方
- autoDisposeとは?
index
[open]
\ アプリをリリースしました /
環境
- Android Studio:Meerkat
- Xcode:16.0
- Flutter:3.29.2
- Dart:3.7.2
- Riverpod:2.6.1
- Mac M1:Sequoia 15.4
familyメソッド
Riverpodのfamily
は引数を受け取り一意のProviderを生成するメソッドです。その際に引数に渡された値を識別子としてProviderインスタンスをキャッシュし再利用できる状態にしてくれます。
// Providerの作成時に引数`id`を渡せるようになる
final userProvider = Provider.family<User, int>((ref, id) => fetchUser(id));
つまり引数にAを渡してProviderを生成した後に、再度引数Aを渡してProviderを生成しようとした際にはキャッシュされたProviderが利用されるので冗長な生成処理を排除してくれます。定義したProviderを使う際は引数の指定が必須になります。
ref.watch(userProvider); // ERROR myProvider is not a provider
ref.watch(userProvider(1)); // 初回:生成されてキャッシュ
ref.watch(userProvider(1)); // 2回目:キャッシュが再利用される
ref.watch(userProvider(2)); // 異なる引数:別のインスタンスが新たに作られる
引数に渡すオブジェクトは等価性が求められる
family
では1つの引数しか渡すことができない仕様になっています。これはその値が識別子としての役割を持っているためでした。複数の引数を渡したい場合は独自のクラスなどを定義してそのプロパティに指定する形にすることで渡すことが可能です。ただその場合は比較可能で、同じオブジェクトと識別できるようにしておく必要があります。
例えば引数用のQuery
クラスを定義する場合は==
とhashCode
をoverride
して比較可能かつ等価であることが証明できるように実装する必要があります。
class Query {
final String keyword;
final int page;
const Query(this.keyword, this.page);
@override
bool operator ==(Object other) =>
other is Query &&
other.keyword == keyword &&
other.page == page;
@override
int get hashCode => keyword.hashCode ^ page.hashCode;
}
autoDisposeで安全に管理
family
ではProviderをキャッシュしてくれますがその扱いには注意が必要です。Providerは参照されなくなっても破棄されないのがデフォルトの動作であるためメモリリークにつながる可能性があります。これを防ぐためにはautoDispose
を使用します。
autoDispose
を付与することで参照がなくなったタイミングで自動で破棄してくれるようになります。
final userProvider = FutureProvider.autoDispose.family<User, int>((ref, id) {
return fetchUser(id);
});
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。