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