はじめに
Flutterで多用するStatefulWidget
のライフサイクルについてまとめています。
Flutterのライフサイクルというと、
- アプリ (
AppLifecycleState
) - 画面 (
StatefulWidget
) ← 今回の内容
の2種類がありますが、今回は下のStatefulWidget
のライフサイクルについての内容です。
アプリのライフサイクルについては、Flutterアプリのライフサイクルを参照してください。
StatefulWidgetのライフサイクル
最初にライフサイクルの状態遷移図を以下に示します。
グレーの四角がStatefulWidget
の状態遷移時に呼ばれるメソッド名を示しており、それ以外がStatefulWidget
の状態名を示しています。
StatefulWidget
のソースコードを見てみると、以下のように内部では4状態が定義されています。
/// Tracks the lifecycle of [State] objects when asserts are enabled.
enum _StateLifecycle {
/// The [State] object has been created. [State.initState] is called at this
/// time.
created,
/// The [State.initState] method has been called but the [State] object is
/// not yet ready to build. [State.didChangeDependencies] is called at this time.
initialized,
/// The [State] object is ready to build and [State.dispose] has not yet been
/// called.
ready,
/// The [State.dispose] method has been called and the [State] object is
/// no longer able to build.
defunct,
}
created状態
StatefulWidget
.createState
によりstateクラスの状態がcreated
になります。ウィジェットが親ウィジェットに接続される (mount
される) と、initState()
がコールされ、状態がinitialized
に遷移します。
initState()
はWidget初期化時に最初に一度だけ呼ばれるメソッドですが、この時点ではBuildContext
の情報は構築されておらず、利用することは出来ません。
BuildContext
とは親ウィジェットの状態や情報などの描画制御のための情報を管理しているコンテキストのことです。グラフィックスやUIフレームワークではよく出てくる考え方に近いですが、これについては別途解説したいと思います。
@override
void initState() {
super.initState();
// todo: ここに処理を書く
}
initialized状態
initState()
完了後、すぐにこのinitialized
状態に遷移します。ここで親ウィジェットのElement (BuildContext) が生成されたあとで、didChangeDependencies()
をコールします。この時点でBuildContext
が利用できるようになる (ただし、引数で) ため、それが必要な初期化処理をここで行います。
@override
void didChangeDependencies() {
super.didChangeDependencies();
// todo: ここに処理を書く
}
ready状態
didChangeDependencies()
完了後、ready
状態に遷移します。
初回構築時にはbuild()
がすぐにコールされ、初回の描画対象のウィジェットが構築されます。
setState()
を行うことで、強制的にウィジェットの再構成 (build
) が行われ、再描画が行われます。
また、親ウィジェットが再構築された時には、didUpdateWidget()
がコールされます。このコールの後、再構築 (build
) が行われますので、setState()
は不要です。それ以外の更新処理が何かあれば、ここで対応します。
@override
void didUpdateWidget(MyHomePage oldWidget) {
super.didUpdateWidget(oldWidget);
// todo: ここに処理を書く
}
defunct状態
ウィジェットが完全に破棄された状態です。
この状態に来る前にdispose()
がコールされますので、このタイミングでウィジェット破棄に伴う終了処理を行うと良いです。
@override
void dispose() {
// todo: ここに処理を書く
super.dispose();
}