くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

【Flutter】Riverpodを使って状態を管理する

Flutterの状態管理について悩んでいたけど、monoさんの記事を読んで、
Riverpodが良さそうだったので、試してみたときの備忘録。

登場人物

進化が早いのと積み重ねが多いので、登場人物が多い。
それぞれ、雑に説明。こんな感じ。

  • 状態の保持
    • アプリの状態(=データの集合)の保持/取得をサポートするライブラリ。親Widgetでも子Widgetでもデータを取得/更新しやすくする
    • Riverpod ... Providerの進化版
  • 値の変更したときの通知
    • 状態が変わったときに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を使うとよいっぽい。

たくさん登場人物がいて、初見だとわかりにくいけど、
理解できるとかなり楽。。(´ω`)

以上!!

参考にしたサイト様