🔗

Providerとは

に公開

Provider

provider は「データや処理を入れておく箱」です。
次の3つの要素でできています。

① 値(state / データ)

provider が「管理しているデータ」のこと。
この中身は固定のデータでもいいし、計算結果やAPIの返り値(非同期処理)でもOK。

// 単純に文字列を提供する
final messageProvider = Provider((ref) => "Hello Riverpod!");

// 計算結果を提供する
final counterProvider = StateProvider((ref) => 0);

// APIリクエストを提供する
final activityProvider = FutureProvider((ref) async {
  final res = await http.get(Uri.parse("https://boredapi.com/api/activity"));
  return jsonDecode(res.body)["activity"];
});

provider の中身は「値」や「処理(ロジック)」そのもの。

② 状態管理の仕組み

providerの中では「どうやって値を保持・更新するか」が決まっています。

(主な種類)
Provider:読み取り専用の値
StateProvider:シンプルに「値を更新できる」状態管理
FutureProvider:非同期で取得した値を提供する
StreamProvider:断続的に最新の値を提供する

つまり「どの種類のproviderか」で、中身の動き方(状態の扱い方)が変わる。

③ 依存関係(ref)

providerの中では、refを使って他のproviderを読み取れる。
つまり「中身同士をつなげて構成できる」。

例:税金を計算するprovider
final priceProvider = Provider((ref) => 1000);

// priceProviderに依存して消費税込みの金額を計算
final taxPriceProvider = Provider((ref) {
  final price = ref.watch(priceProvider);
  return (price * 1.1).toInt();
});

providerの中身は「単独の値」だけじゃなく、他のproviderを組み合わせた計算結果にもできる。

Providerの値を参照する方法

次に、これらのProviderの値を参照、

① ref.watch(provider)

値を監視しながら参照する
UI が provider の値を監視する
値が変わったら UI が自動で再描画される

final messageProvider = Provider((ref) => "Hello Riverpod!");

class Home extends ConsumerWidget {
  
  Widget build(BuildContext context, WidgetRef ref) {
    final message = ref.watch(messageProvider); // ← 参照
    return Text(message); // "Hello Riverpod!" が表示される
  }
}

UI でよく使う方法
StateProvider の値が変わったら、自動で画面が更新される

②ref.read(provider)

1回だけ値を参照する(監視しない)
値が変わっても UI は更新されない

例:「ボタンを押した時だけ」「初期化の時だけ」など

final counterProvider = StateProvider((ref) => 0);

class Home extends ConsumerWidget {
  
  Widget build(BuildContext context, WidgetRef ref) {
    return ElevatedButton(
      onPressed: () {
        // 監視しないで今の値を1回だけ取得
        final value = ref.read(counterProvider);
        print("現在のカウント: $value");
      },
      child: Text("カウントを確認"),
    );
  }
}

③ ref.listen(provider, ...)

値の変化を監視してコールバックを実行
値が変わった時に「副作用(サイドエフェクト)」を発生させたいときに使う

例:ログを出す、Snackbar を表示する、ナビゲーションする など

class Home extends ConsumerStatefulWidget {
  
  ConsumerState<Home> createState() => _HomeState();
}

class _HomeState extends ConsumerState<Home> {
  
  void initState() {
    super.initState();
    ref.listen<int>(counterProvider, (previous, next) {
      print("カウントが $previous$next に変わった!");
    });
  }

  
  Widget build(BuildContext context) {
    final count = ref.watch(counterProvider);
    return Text("カウント: $count");
  }
}

④ ref.refresh(provider)

provider をリセットして再取得
FutureProvider や StreamProvider で「もう一回データを取り直したい」ときに使う

ElevatedButton(
  onPressed: () {
    ref.refresh(activityProvider); // APIを再リクエスト
  },
  child: Text("更新"),
);

まとめ

【providerの3つの要素】
値(データや処理):文字列、数値、モデル、APIの返り値、など
状態管理の仕組み:Provider(固定値)、StateProvider(更新可能)、FutureProvider(非同期)、など
依存関係(ref):他の roviderを参照して組み合わせができる

【Providerの参照方法】
ref.watch:監視しながら値を参照(UI用)
ref.read:1回だけ値を参照(イベント処理用)
ref.listen:値の変化に応じて処理を走らせる(副作用用)
ref.refresh:再取得したいときに使う

Discussion