Flutterの状態管理について悩んでいたけど、monoさんの記事を読んで、
Riverpodが良さそうだったので、試してみたときの備忘録。
登場人物
進化が早いのと積み重ねが多いので、登場人物が多い。
それぞれ、雑に説明。こんな感じ。
- 状態の保持
- 値の変更したときの通知
- 状態が変わったときにWidgetも更新されるようにするため、変更の通知を受け取れるようにする
- StateNotifier ... ValueNotifierの進化版
- Widgetから状態へのアクセス
- StatefulWidgetを簡潔に書けるようにする
- Flutter Hooks
Riverpodでprividerから別のprividerを参照できることもあり、
NuxtのVuex(Store)みたいな感じがしてる。
(Providerパッケージとproviderがあるので、すこしわかりずらい。。)
インストール
まずは、pubspec.yamlにdependenciesを追加。
// pubspec.yaml dependencies: // ... flutter_hooks: ^0.14.0 hooks_riverpod: ^0.11.0
flutter packages get
して、変更を反映する。
$ flutter packages get
stateとproviderを用意する
以下の感じで、3つを用意する。
StateNotifierは1つの値しか保持できないので、別途データクラスが必要。
// privider final counterProvider = StateNotifierProvider((_) => CounterState()); // state class CounterState extends StateNotifier<Counter> { void countup() { state.count = state.count + 1; } } // stateで保持するデータクラス class Counter { int count = 0; }
flutter_hooksから、providerを使ってみる
まず、Riverpodを利用できるよう、ProviderScopeでwrapする。
RiverpodはProviderScope配下のWidgetでのみ利用できる。
// main.dart // ... void main() => runApp(ProviderScope(child: MyApp()));
これでWigetから使えるようになる。
class MyApp extends HookWidget { @override Widget build(BuildContext context) { // useProviderで、providerから値やStateNotifierを取得できる。 // useProviderは、build()でしかつかえない。 final state = useProvider(counterProvider.state); final counter = useProvider(counterProvider); // 取得したら、stateの値やStateNotifierのメソッドを呼び出せる return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Counter')), body: Center( child: Text(state.count.toString()), ), floatingActionButton: FloatingActionButton( onPressed:() => counter.countup(), child: Icon(Icons.add), ), ), ); } }
また、ドキュメントの「Rules」にもある通り、
useProviderなど、useXXXを利用できるのは、build()ないだけなので、注意。
・Rules | flutter_hooks | Flutter Package
まとめ
- Riverpodを使うと状態の保持やアクセスが簡単になる。
- StateNotifierを使うと、状態が変わったときに通知され、Widgetも更新される。
- StatefulWidgetなどは煩雑だったけど、HookWidget(flutter_hooks)だとすっきり書ける。
上記の例は、データクラスがmutableだけど、
immutableにしたい場合は、freezedを使うとよいっぽい。
たくさん登場人物がいて、初見だとわかりにくいけど、
理解できるとかなり楽。。(´ω`)
以上!!