Flutterやってみたよ part3 (アーキテクチャ調査編)


はじめに

前回に引き続きFlutterアプリの製造を行っていきます。
今回はアーキテクチャを選択するためそれぞれのアーキテクチャについて調べようと思います。

そもそも状態管理って?

初心者の方なら?状態管理って何?必要なの?となると思いますのでここはちゃんと理解しておこうと思います。ここを理解していないとたぶん適切なパターンを選べないです。

以下のmonoさんの記事がともわかりやすかったです。

[参考]

ざっくり要約するとは大まかに3つで成り立っていて

  • Widget: ステートレス・immutable・軽量・設計図
  • Element: ステートフル・mutable・WidgetとRenderObjectの仲介役
  • RenderObject: ステートフル・mutable・レンダリングを担う

Widgetは状態を持っていないただの画面の部品で、RenderObjectがレンダリング(描写)を行います。
そこにElementがWidgetとRenderObjectに相互に状態を伝え画面の描画が実現されます。
これがツリー構造になっていて画面が出来上がります。

毎回全部の部品を作り直していたらコストパフォーマンス的に悪いので、特定のwidgetのみ状態によって再描画するように開発者は気をつける必要があります。誰でもサクサク動くアプリの方がいいですよね?単純な画面ならいいですが、実際に業務で作る画面とかは複雑な画面もあると思います。
そこで状態管理の手法がいくつか用意されているってことらしいです。

状態管理の方法って何があるの?

調べてみたところ公式サイト(List of state management approaches)では以下の6つについて書かれています。

  • setState
  • InheritedWidget & InheritedModel
  • Provider & Scoped Model
  • Redux
  • BLoC / Rx
  • MobX

などがあるそうです。
どれも素晴らしい記事があるので詳細は割愛してざっくり要約だけ書きます。

setState

標準の機能ですね。
特段言及するところはありません。setState()を呼び出すことで状態の更新を行います。

    setState(() {
      aaa = 'bbb';
    });

InheritedWidget & InheritedModel

標準で用意されているwidgetを駆使する手法です。

  • 子孫が親の変更を感知できる
  • buildメソッドを再度呼ぶことで再構築し直すことができる
  • 先祖をO(1)で取得できる

やっぱり不必要なwidgetのビルドをコントロールしましょうねってことですね。
InheritedWidgetはBLoCでも使用されていますのできちんと理解しておくと良さそうです。

[参考]

Provider & Scoped Model

ここからはライブラリを使用します。
ライブラリ:scoped_model

基本的にはModelで囲むってだけでStatefullWidgetとStateを意識する必要がなくなるのでシンプルに感じます。小さめのアプリだったらこれで行けそう気がします。

[参考]

Redux

ライブラリ:reduxflutter_redux など

Javascriptのために考えられた設計で、仕組みは最もシンプルでわかりやすいと思います。
アプリ内の全状態のStore(json的なもの)があって、前の状態とアクションを組み合わせて新しい状態を生み出すという状態管理手法です。これによって画面によって状態が異なる現象を防げるのもいいですね。
そしてテストコードも書きやすいとのことなので、これは結構使えそうな気がします。
まだ開発に慣れていない人とか品質を意識する必要がある時とかに向いている気がします。

[参考]

BLoC

ライブラリ:blocflutter_blocbloc_patternhydrated_blocbloc_provider など

Blocは最も多く導入されているであろう状態管理手法で、Googleも推奨しているとのこと。
Business Logic Componentの略でビジネスロジックとUIを明確に分けることを目的としています。
BLoCの原則は以下の3つです。

  • インプットとアウトプットは、単純なStreamとSinkに限定する。
  • 依存性は、必ず注入可能でプラットフォームに依存しないものとする。
  • プラットフォームごとの条件分岐は、許可しない。

上記を満たしていればあとはどんな作りでもOKとのこと。

Blocに保持しているデータをStreamとSinkを使って伝搬させることによって非同期でwidgetを更新させることができます。

[参考]

MobX

ライブラリ:mobxflutter_mobx

MobXはReduxと同様にJavascriptのために考えられた設計で、Observables・Actions・Reactionsの3つで成り立っています。
アノテーションをつけることで3つの状態を関連付けています。javaっぽい書き方ですね。

[参考]

まとめ

全てのアーキテクチャについて調べてみましたが、個人的に気にいったのはRedux。テストのことも考えると良さげです。
もう一つはGoogleおすすめのBLoC。Rx使ってるのでやっぱりしっくりきます。

次回は早速アーキテクチャ導入編としてReduxBLoCの導入サンプルを作りたいと思います!
ではまた👋

参考

大変勉強になりました。ありがとうございます🙇‍♂️