Flutter
Flatterの世界でもWebフロントエンドよろしく状態管理方法の流行り廃りがあるらしく何を使っていいかよくわからない状態になっていたので現状をまとめる意味でもメモをのこしておく。
StatefulWidget
一番素朴な状態管理の方法。StatelessWidgetの違いは、StatelessWidgetが 初期化時に渡された情報しか扱えない (フィールドを持ったとしてもfinalを指定する必要がある) のに対して StatefulWidget は可変のフィールドを持てるという点。
状態のアップデートの時には setState(() { _value = 42; })
のようにsetStateに関数を渡す形で変更する。setStateが呼び出されると次のフレームで build() が呼び出されて表示が切り変わる的な実装?なのかな?
欠点としては 実装が素朴すぎて当該クラス外の状態を変更したりするのが苦手、という面があるらしい。
たとえば子Widgetのボタンが押されたら何かをしたい、といった場合に子Widgetのコンストラクタにボタン押された時呼ばれるコールバックをいちいち渡してあげなかったり、となりのWidgetの状態に応じて内容を変えたいみたいな時にすごいとっちらかるみたい。
ひいてはアプリケーション内の色々な所に状態をもったWidgetが広範囲で散らばるということになるので、想像しただけでもバグりそう。
逆にいうと1ページしかないシンプルなアプリケーションだったり、Widget内でしか使わない状態を管理する分には全然これで十分、ということになる模様
これだとしんどいでしょっていう流れから、すでに色々な人が解決策を模索していて色々なライブラリが出てきている。沢山あるのでよさそうなものだけつまんで試してみた。
【Flutter】StatefulWidget の2つの問題点。どうして実践ではあまり使われないか?その代わりにどうすればいいか?|石川 陽太|note
Provider, Riverpod
(そんなに詳しくないけど)Webフロントエンド界隈では、状態は個々のコンポーネントが個別に持つのではなく、アプリケーション内の状態を集中的にする仕組みに全部つっこんでおいて、状態変更のを検知して描画の更新が必要なコンポーネントだけを更新する、といったメカニズムを使うのが今風になっている、という雰囲気を感じており、Flutterでもその流れを組むような試みがいくつかあった。
いくつか見た中でコード片レベルでわかりやすそうだなと思ったのが provider というもので、同じ作者の人が新しく作りなおした Riverpod というライブラリがよさそうだなと思って使ってみることにした。
アプリケーションで扱う状態をグローバルスコープに宣言した状態管理クラス(Provider) に全部入れて、そこにアクセスするには専用の仕組み (ConsumerWidget、Consumerクラス) を通じてやってね、みたいな使い方のようだった。ニュアンスとしては行儀のいいグローバル変数
情報のたまり場がグローバルスコープに宣言されているのでどこからでもアクセスできるし、状態が変わったら適時再描画が走るようになる。
Webでよく見かける情報で Riverpod と state_notifier というのを一緒に使う、といった記述をよく見かけて何が違うのかよくわからなかったのだが、state_notifier を使うとグローバルスコープにある Provider に状態だけではなくメソッドも追加できる、という感じになるらしい。
state_notifier も Riverpod と同じ作者の人が作っているようで、Riverpod をインストールしたら依存で入るみたい。なのであえて分けて考えなくてもよさそうだった。
Riverpod 内に入っている Provider にも色々とサブクラスがあって一体何が違うのか… と思っていたんだけど、メソッドも定義できて使い勝手よさそうなので StateNotifierProvider 使ってればいいんじゃないかな という雰囲気を感じた
ほかにも react_hooks の使い勝手をflutterでも使いたい人向けの亜種もあったのだがreactつかったことないし混乱度が増しそうなのでスキップした
freezed
状態管理とは直接関係はないけど、データクラスを immutable にするための freezed というライブラリも色々な所で見かけたので試してみた。
仕組みとしてはデータクラスを定義する時にソースコードにアノテーションをつけておくことで、imuutableにするためのコードをソースコードジェネレーターで生成してくれる君、というかんじのようだった。
imuutable にして何が嬉しいのか雰囲気でやってるのであまりわかってはいないが、そんなに手間もかからないし、printした時の表示もリッチになり、ちょっとした追加でjsonのシリアライズ/デシリアライズまでできてくれるようなので細かいことはあまり気にせず データクラスはとりあえず freezed でいいような気がした
freezed | Dart Package
freezed パッケージの使い方【Flutter/Dart】|石川 陽太|note