ライフサイクルとは
ライフサイクルとは、人間でいうと誕生してから死ぬまでのこと
この記事の文脈では、画面が誕生してから消滅するまでのこと
です!
StatelessWidgetのライフサイクル
abstract class StatelessWidget extends Widget {
/// Initializes [key] for subclasses.
const StatelessWidget({ Key? key }) : super(key: key);
/// Creates a [StatelessElement] to manage this widget's location in the tree.
///
/// It is uncommon for subclasses to override this method.
@override
StatelessElement createElement() => StatelessElement(this);
@protected
Widget build(BuildContext context);
}
StatelessWidgetの中身を具体的に見ていきます。
最も重要な部分:createElementメソッド
このメソッドでStatelessElementをインスタンス化しています。
StatelessWidgetに限らずウィジェットクラスはcreateElementでエレメントを必ずインスタンス化します。
FlutterはWidgetをツリー構造で作成していくので、ツリー構造という概念をご存知だと思います。
Elementもまた同じツリー構造になります!!
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Text("テキスト"),
),
),
);
}
}
具体的に見ていきましょう!
(MyAppは抽象クラスのStatelessWidgetを継承しているので、buildメソッドを必ず実行しなければなりません。)
上のMyAppクラスがインスタンス化されると、StatelessElementクラスもインスタンス化されます。
その時、StatelessElement()の引数に自分自身を代入しています。
これはどういうこのなのでしょうか?
@override
StatelessElement createElement() => StatelessElement(this);
以下のような状態になっています。
StatelessElementクラスがMyAppクラスを参照しています。
ここで、MyAppの下のMaterialAppはStatefulWidgetを継承しているのでStatefulElementが作成されます。そして、StatefulElementはMaterialAppを参照します。この作業がTextまで繰り返されて、WidgetとElementのツリー構造が形成されます。そして、ElementとWidgetは一対一の関係で参照しています。
StatelessWidgetは、構築されたときに1回しか描画されないウィジットです。ユーザーアクションに基づいて再描画されることはありません。
てことで、StatelessWidgetのライフサイクルは2つです。
StatelessElementを作成してエレメントツリーに追加する前のinitial状態と、追加した後のactiveの状態になります。
StatefulWidgetのライフサイクル
StatefulWidgetクラスの場合は、ちょっぴり複雑です。
まずは、StatefulWidgetクラスのソースコードをみよう。
abstract class StatefulWidget extends Widget {
/// Initializes [key] for subclasses.
const StatefulWidget({ Key? key }) : super(key: key);
/// Creates a [StatefulElement] to manage this widget's location in the tree.
///
/// It is uncommon for subclasses to override this method.
@override
StatefulElement createElement() => StatefulElement(this);
@protected
@factory
State createState();
}
StatelessWidgetと同様にWidgetクラスを継承しており、createElement()メソッドがあります。
StatefulElementのソースコードの中には、Stateオブジェクトを保持しています。
/// The [State] instance associated with this location in the tree.
///
/// There is a one-to-one relationship between [State] objects and the
/// [StatefulElement] objects that hold them. The [State] objects are created
/// by [StatefulElement] in [mount].
final State<StatefulWidget> state;
つまり、StatefulWidgetはStatelessWidgetと同様に変更可能な状態を保持しておらず、State<StatefulWidget>
を保持して、状態を管理しています。
setState()メソッド
StatefulWidgetクラスの醍醐味はStateクラス内の値を変化さえることで再描画することです。再描画したいときに呼び出すのがsetState()です。これが呼ばれることで、build()メソッドが再実行されます。もう少し勉強していくと、アプリを全てStatelessWidgetクラスで作ることも可能です。その時も同様にStatelessWidgetクラス内のWidgetがStatefulWidgetを継承していて、内部でsetState()を実行しています。