Reading a provider
このガイドを読む前に、まずProvidersをお読みください。
このガイドでは、プロバイダを使う方法について説明します。
プロバイダのreadする方法は複数あり、基準によって少しずつ異なります。
長くなりましたが、ここでは、プロバイダをreadするときに何を使うかを決めるための判断グラフを紹介します。
次に、個々のケースを見て、その仕組みを紹介します。
このガイドでは、以下のプロバイダーを検討します。
#
何をreadするかを決めるlistenしたいプロバイダによっては、listen可能な値が複数ある場合があります。
例として、次のようなStreamProviderを考えてみましょう。
このuserProvider
をreadするときには
userProvider
自身をlistenすることで、現在の状態を同期的にreadする:userProvider.stream
をlistenして、関連する[Stream]を取得する:userProvider.last
をlistenして、emitされた最新の値で解決する[Future]を取得する:
詳細は、APIリファレンスを参照して、各プロバイダのドキュメントを参照してください。
#
Widgetの中でプロバイダを使うこのセクションでは、FlutterのWidgetがどのようにプロバイダと連携するかを見ていきます。
#
ConsumerWidgetConsumerWidget は、StatelessWidget
に似たウィジェットのベースクラスですが、プロバイダをlistenすることができます。
counterProvider
の値がどのようにwatch
という関数で取得されているかに注目してください。
この関数は、ConsumerWidgetがプロバイダをlistenし、値が変更されたときに再構築するためのものです。
caution
ConsumerWidgetの引数として渡されるwatch
メソッドは、
onPressed
やElevatedButtonの内部のように、非同期的に呼び出されるべきではありません。
ユーザーイベントに応じてプロバイダをreadする必要がある場合は、context.read(myProvider)を参照してください。
#
ConsumerConsumerはConsumerWidgetであり、データを使用する必要のあるWidgetのみを再構築することで、
アプリケーションのパフォーマンスを最適化するために使用することができます。
例えば、前に見たConsumerWidgetのコードスニペットを更新して、
カウンターが変更されたときにText
だけを再構築するようにします。
この例では、UIがcounterProvider
をlistenし、カウンターが変更されるとTextをリビルドします(そのTextのみ)。
#
useProvider (hooks_riverpod のみ)flutter_hooks/hooks_riverpodを使用している場合、ConsumerWidgetの代わりに[ref.watch()]を使用することができます。
これはflutter_hooksとRiverpodの両方を併用したい場合に便利です。
この構文は、ConsumerWidgetではサポートされていない機能もサポートしています。[select] です。
この構文を使うと、isAbove5
変数が変化した場合に のみ 、Widgetが再構築されます。
つまり、カウンターが 1
から 2
に変更されても、 Widgetが再構築されることはありません 。
#
context.read(myProvider)Consumerと[ref.watch]では、プロバイダを listen する方法を見てきました。
しかし、状況によっては、そのオブジェクトをlistenする価値がないこともあります。
例えば、ElevatedButtonのonPressed
のためだけにオブジェクトが必要な場合があります。
私たちは、[ref.watch]/Consumerを使用することができます。
しかし、それでは効率が悪いでしょう。
listenされたプロバイダによっては、カウンタが実際にはElevatedButtonの構築に使用されていなくても、
カウンタが変更されたときにElevatedButtonが再構築されることがあります。
そこで、context.read(myProvider)
が解決策となります。
これを使うことで、以前のコードをリファクタリングします。
こうすることで、ボタンをクリックしても、カウンターは増えていきます。
しかし、無駄なリビルドを避けるために、プロバイダをlistenしなくなっています。
context.read
メソッドが見当たらないのですが、これはなぜでしょうか?
もし、context.read
が表示されない場合は、正しいパッケージをインポートしていない可能性があります。
このメソッドを表示するには、package:flutter_riverpod
またはpackage:hooks_riverpod
のいずれかをインポートする必要があります。
info
listenするプロバイダによては、この作業が必要ない場合もあります。 例えば、StateNotifierProviderは、StateNotifierの状態をlistenせずに取得する方法を内蔵しています。
caution
Widget の build
メソッド内での context.read
の呼び出しを避けてください。
リビルドを最適化したい場合は、代わりにProviderでlistenされた値を抽出します。
#
ProviderListenerプロバイダの変更後にルートをプッシュしたり、ダイアログを表示したりするために、
Widgetツリーが必要になる場合があります。
このような動作は、ProviderListener Widgetを使用して実装されます。
これにより、カウンターが5に達したときにダイアログが表示されます。
#
プロバイダの中で別のプロバイダをreadするプロバイダーを作る際によくあるのが、他のオブジェクトからオブジェクトを作りたいというケースです。
例えば、UserRepository
からUserController
を作成したい場合、
両方のオブジェクトは別のプロバイダで公開されます。
このようなシナリオは、プロバイダがパラメータとして受け取る ref
オブジェクトを使用することで可能になります。
Combining Providers(プロバイダーの組み合わせ)のガイドには、
以下のような情報が掲載されていますので、ぜひご覧ください。
- 時間の経過とともに変化する値からオブジェクトを作成するとどうなるか?
- いくつかのグッドプラクティス
#
Dartのみの場合のプロバイダ外のプロバイダのread場合によっては、Flutterに依存していないパッケージのプロバイダをreadしたいこともあるでしょう。
よくあるケースは、Widgetとは関係のないクラスをテストする場合です。
このような状況では、プロバイダを操作するための低レベルのユーティリティであるProviderContainerを使用することができます。
次のスニペットは、Flutterを使わずにテストでプロバイダをreadする方法を示しています。
danger
ProviderContainerのインスタンスをテスト間で再利用しないでください。 これにより、テストケース間でプロバイダの状態が適切にリセットされるようになります。