目次
概要
Flutterでは単純に画面を構成するStatelessウィジェットは違って、Statefulウィジェットはライフサイクル(lifecycle
を持っています。今回のブログポストではStatefulウィジェットのライフサイクについて説明します。
Flutterのライフサイクル関数の理解を助けるため例題を作りました。下記のリンクでソースコードを確認することができます。
- GitHub: lifecycle
Statelessウィジェット
Statelessウィジェットは単純に画面を構成するウィジェットなので、複雑なライフサイクルを持ってないです。それではStatelessウィジェットのライフサイクル関数についてみてみましょう。
StatelessウィジェットのConstructor
Flutterでウィジェットは基本的クラスを使って生成します。ウィジェットは基本的クラスで構成されるので、同然ながらクラスのコンストラクタ(Constructor)
を使うことができます。
ウィジェットのコンストラクタはクラスのコンストラクタと同じ役割をして、ウィジェット(クラス)中の使う変数を初期化する時使います。
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
final String title;
Home({required this.title});
...
}
Statelessウィジェットのbuild
ウィジェットのbuild
関数は画面に表示される内容を作成します。これはReact
のrender
関数と同じ役割をして、画面に表示されるウィジェットをリターンします。
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
...
@override
Widget build(BuildContext context) {
return Center(
child: Text('Setting Screen'),
);
}
}
Statelessウィジェットはステート(State)を持ってません。したがって、親ウィジェットから渡してもらった値が変更されるとウィジェットがrebuild
され、画面を更新することになります。この時Constructor
とbuild
が再実行されます。
Statefulウィジェット
StatefulウィジェットはStatelessウィジェットとは違ってウィジェットがステート(State)を持ってるので、ウィジェットのライフサイクルが複雑です。それではStatefulウィジェットのライフサイクル関数を見てみましょう。
StatefulウィジェットのConstructor
Statefulウィジェットのコンストラクト(Constructor)もStatelessウィジェットのコンストラクトと同じ役割をします。ウィジェットクラスでインスタンスを作る時、コンストラクトが一番最初コールされて、親ウィジェットからパラメータを貰う時使います。
class CounterContainer extends StatefulWidget {
final int count;
CounterContainer({required this.count})
@override
_CounterContainerState createState() => _CounterContainerState(count: count);
}
class _CounterContainerState extends State<CounterContainer> {
int count;
_CounterContainerState({required this.count})
...
}
initState
Statefulウィジェットが生成される時、一回
だけコールされる関数で、ステート(State)の値を初期化する時使います。
class _CounterContainerState extends State<CounterContainer> {
late int count;
@override
void initState() {
super.initState();
count = 0;
}
...
}
didChangeDependencies
この関数はウィジェットが生成される時、initState
関数がコールされた直後、一回コールされます。また、InheritedWidgetやProviderを使う場合、InheritedWidgetやProviderの内容が変わると、コールされます。
@override
void didChangeDependencies() {
super.didChangeDependencies();
print('_MyHomePageState didChangeDependencies');
}
つまり、親ウィジェットや自分のステートが変更される時はコールされないですが、当該ウィジェットが参照(Depedency)するウィジェット(InheritedWidgetまたはProvider)が変更されるとdidChangeDependencies
関数がコールされます。
didUpdateWidget
この関数は親ウィジェットによってrebuild
が必要な時、build
関数がコールされる直前にコールされます。普通、親ウィジェットの変更によって、アニメーションを再実行する必要がある時、良く使います。
@override
void didUpdateWidget(MyWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.value != oldWidget.value) {
// TODO: start a transition between the previous and new value
}
}
また、親ウィジェットの変更しによってステートを初期化する必要がある場合、この関数でsetState
を使ってステートを再初期化することができます。
Statefulウィジェットのbuild
Statelessウィジェットのbuildと同じ役割をします。画面に表示されるウィジェットをリターンする時使います。setState
を使ってStatefulウィジェットのステート(State)が変わるとき、再びコールされ画面を更新します。
deactivate
StatefulウィジェットはStatelessウィジェットは違ってステート(State)オブジェクトを持っています。このステートオブジェクトが変更(dirty)されると、変更されたステートオブジェクトを使ってStatefulウィジェットをrebuild
します。
deactivate
関数はステート(State)オブジェクトがツーリで削除される時、コールされます。Flutterは時々ステータオブジェクトでけ消して、また追加する場合があります。例えばGlobalKey
を使って現在のウィジェットをウィジェットツーリの特定な位置に移動させると、当該ウィジェットのステータオブジェクトが変更されdeactivate
が実行されます。
詳しい内容は公式ドキュメントを参考してください。
- 公式ドキュメント: deactivate
dispose
ウィジェットオブジェクトがウィジェットツーリから永遠に削除される時、コールされます。ウィジェットツーリから完全に削除されるので、ステートオブジェクトも一緒に削除されます。ステータオブジェクトが削除されるので、deactivate
が先コールされ、ステータオブジェクトが削除された後、dispose
がコールされウィジェットが削除されたことを教えてくれます。
dispose
関数のコールはウィジェットが永遠に削除されたことを意味するので、setState
を使って当該ウィジェットのrebuild
をすることができません。
コールの順番
- Statefulウィジェットが生成される時:
Constructor
>initState
>didChangeDependencies
>build
- setStateがコールされる時:
build
- InheritedWidgetまたはProviderの値が変更された時:
didChangeDependencies
>build
- 親ウィジェットから渡して貰った値が変更される時:
didUpdateWidget
>build
- ステータオブジェクトが削除される時:
deactivate
>build
- ウィジェットオブジェクトが削除される時:
deactivate
>dispose
完了
これでFlutterのウィジェットのライフサイクル(lifecycle)についてみてみました。間違ってライフサイクル関数を使うと、アプリの性能が悪くなったり、無限ループになったりするので注意して使わなきゃならないです。また、ウィジェットのライフサイクルはsetState
や特定な関数のコールタイミングを決定したり、アニメーションの実行時点に重要な役割をするので今回ちゃんと勉強しておきましょう。
私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!
アプリ広報
Deku
が開発したアプリを使ってみてください。Deku
が開発したアプリはFlutterで開発されています。興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。