Flutterの学習で詰まるポイント(1)宣言的UI で書いたように、UIを初期化してからその属性を更新するという方法は取りません。宣言的UIをサポートしているフレームワークでは、UIを初期化した後で、その属性を何かのイベントで書き換えることが出来ない。

FlutterでUIを変更するには、「自分が参照しているデータは更新されたので、UIを再構築(リビルド)しなさい」とWidgetに伝えます。簡単に言うと、Widgetのbuildメソッドを何度も呼び出すことになります。

すごく単純化すると、タップされた数をカウントする機能があって、それを画面に出すコードがあるとします。Text(counter) という形です。Flutterは、以下の理屈でUIを更新します。

  1. ボタンタップで、counter++する
  2. counterが変更されたので、Flutterにbuildの呼び出しを依頼する
  3. Flutterは更新されたcounterで、UIを作り直す
  4. 更新されたcounterによって、UIが表示される

buildを何度も呼び出すと行っても、onPressed: () => build() と書けるわけではありません。build を呼び出すのは、Flutterのフレームワーク側に委ねられます。buildを呼び出すには、Flutterに「このWidgetが参照しているデータが変更されたので、もう1回buildを呼び出す」という依頼を投げることだけです。

データが変更されたことを検知してBuildを呼び出す仕組みに関わってくるのが、Stateです。

Stateって何

Stateは、Widgetのライフサイクルを表現したものです。UIにライフサイクルという概念があることに馴染みがない人が、特にFlutterが初めてのフロントエンド・スマホアプリ開発の人に多い。教えていて、強く感じます。ま、HTMLにライフサイクルが言ってもなんのこっちゃ、ですよね。

Flutterが提唱しているWidgetのライフサイクルは、簡単に言うとこの4つです。

  1. Stateが生成された(created)
  2. 生成されたStateとWidgetが紐づいた(initilized)
  3. Widgetのbuildを呼び出せるようになった(ready)
  4. WidgetがWidget Treeから破棄された(defunct)

これを図式化したのが、こちらの画像です。

setState

上記の図の右側に注目してください。ready→(強制的にウイジェットを再構築)→ setState → buildと書かれていると思います。setStateを呼び出すことで、buildを呼び出すことができます。

floatingActionButton: FloatingActionButton(
      onPressed:() => setState( () => _counter++;),
      tooltip: 'Increment',
      child: const Icon(Icons.add),
  ),

setStateに引数も戻り値も持たない関数を代入して、関数の内部で自分が参照しているデータを更新します。そうすると、新しいデータでbuildが実行されます。build(1), build(2) というイメージを持つと、わかりやすいかもしれません。

Flutterにおいては、上記のStateを自分が好きなように管理できる機能を持ったWidgetのことを、StatefulWidgetと言います。createState, initState, setState, dispose, などが利用できます。

この逆で、Stateに対するイベントハンドラが一切利用できないWidgetのことを、StatelessWidgetと言います。Widgetのライフサイクルに一切タッチすることができない=Stateless、という意味合いです。

ここに書いてある内容は、プログラムの書き方ではありません。Flutterの設計思想の説明です。設計思想が理解できるようになるには、ある程度アプリ開発の経験がどうしても必要です。自分が書いてきたコードの背景には、こういう考えがあったんだなと腑に落ちるまで、時間がかかるため。

Flutterのコードをなぞることはできても、新しい設計思想や考え方を提案できなければ、レベルが上がりません。レベルを上げるには、自分なりに抽象的な概念を図式化する・構造化する訓練が必要です。

次回は、Flutterのサンプルアプリにもカウンターアプリケーションを見ながら、StatefulWidgetとStatelessWidgetの違いをコードで整理し、Stateのライフサイクルについての理解を深められるようにします。