Skip to main content

Providers

さて、Riverpodのインストールが完了したところで、「プロバイダー」について説明します。

プロバイダは、Riverpodアプリケーションの最も重要な部分です。
プロバイダとは、状態の一部をカプセル化し、その状態のリスニングを可能にするオブジェクトのことです。

プロバイダーを使う理由は?#

ステートの一部をプロバイダでラップすることで、

  • 複数の場所でその状態に簡単にアクセスすることができます。 プロバイダは、シングルトン、サービスロケータ、依存性注入、 InheritedWidgetsなどのパターンを完全に置き換えるものです。

  • この状態と他の状態を組み合わせることを簡単にします。
    複数のオブジェクトを1つにまとめるのに苦労したことはありませんか?
    このシナリオは、シンプルな構文でプロバイダの中に直接組み込まれています。

  • パフォーマンスの最適化が可能になります。
    プロバイダは、ウィジェットの再構築をフィルタリングしたり、
    高価な状態計算をキャッシュしたりして、状態変化の影響を受けるものだけが再計算されるようにします。

  • アプリケーションのテスタビリティが向上します。
    プロバイダーを使えば、複雑なsetUp/tearDownの手順は必要ありません。 さらに、どのプロバイダもテスト時に異なる動作をするようにオーバーライドすることができるので、
    特定の動作を簡単にテストすることができます。

  • ロギングやPull-to-refreshなどの高度な機能と簡単に統合できます。

プロバイダーの作成#

プロバイダーにはさまざまな種類がありますが、仕組みは同じです。

最も一般的な使い方は、以下のようにグローバル定数として宣言することです。

final myProvider = Provider((ref) {
return MyValue();
});
note

プロバイダーのグローバルな側面に恐れを抱くことはありません。
プロバイダは完全に不変(immutable)です。
プロバイダを宣言することは、関数を宣言することと同じであり、テスト可能で保守性が高いのです。

このスニペットは3つの要素で構成されています。

  • final myProvider は変数の宣言です。
    この変数は、今後、プロバイダーの状態を読み取るために使用します。
    これは常に不変でなければなりません。

  • Provider, 我々が使用するプロバイダーです。
    Providerは、すべてのプロバイダの中で最も基本的なものです。
    これは変更されることのないオブジェクトを公開します。
    ProviderStreamProviderStateNotifierProviderなど、
    他のプロバイダに置き換えることで、値の操作方法を変更することができます。

  • 関数は共有された状態を作成します。
    この関数は、常にパラメータとして ref というオブジェクトを受け取ります。
    このオブジェクトは、他のプロバイダを読み込んだり、
    自分のプロバイダの状態が破棄されるときにいくつかの操作を実行することができます。

プロバイダーに渡された関数で作成されるオブジェクトのタイプは、
使用するプロバイダーによって異なります。
例えば、Providerの関数は、任意のオブジェクトを作成することができます。
一方、StreamProviderのコールバックは、Streamを返すことが期待されます。

info

プロバイダーは制限なくいくつでも宣言できます。
package:providerを使う場合とは異なり、
Riverpodでは2つのプロバイダが同じ「タイプ」の状態を公開することができます。

final cityProvider = Provider((ref) => 'London');
final countryProvider = Provider((ref) => 'England');

どちらのプロバイダーも String を作成するという事実は何の問題もありません。

caution

プロバイダを動作させるには、FlutterアプリケーションのルートにProviderScopeを追加する必要があります。

void main() {
runApp(ProviderScope(child: MyApp()));
}

状態破壊前のアクションの実行#

場合によっては、プロバイダの状態が破壊されたり、再作成されたりすることもあります。
このような状況での一般的な使用例は、StreamControllerをクローズするなど、
プロバイダの状態が破壊される前にクリーンアップを実行することです。

これは、すべてのプロバイダのコールバックに渡される ref オブジェクトを使って行われ、onDispose メソッドを使います。

次の例では、onDisposeを使ってStreamControllerを close します。

final example = StreamProvider.autoDispose((ref) {
final streamController = StreamController<int>();
ref.onDispose(() {
// このプロバイダの状態が破壊されると、StreamControllerをcloseします。
streamController.close();
});
return streamController.stream;
});
note

使用するプロバイダーによっては、すでに後始末をしてくれる場合もあります。
例えば、StateNotifierProviderStateNotifierdisposeメソッドを呼び出します。

Provider Modifier#

すべてのプロバイダには、異なるプロバイダに追加機能を追加する方法が組み込まれています。

それらは、refオブジェクトに新しい機能を追加したり、プロバイダの消費方法を少し変えたりします。
Modifierは、名前付きコンストラクタと同様の構文で、すべてのプロバイダで使用できます。

final myAutoDisposeProvider = StateProvider.autoDispose<String>((ref) => 0);
final myFamilyProvider = Provider.family<String, int>((ref, id) => '$id');

現時点では、2つのmodifierが用意されています。

  • .autoDispose,
    プロバイダがリストアップされなくなったときに、その状態を自動的に破壊するようにします。
  • .family,
    外部のパラメータからプロバイダを作成することができます。
note

プロバイダーは一度に複数のModifierを使用することができます。

final userProvider = FutureProvider.autoDispose.family<User, int>((ref, userId) async {
return fetchUser(userId);
});

今回のガイドはここまでです。

How to read a providerを続けてご覧いただけます。
または、How to combine providersをご覧ください。