StatelessWidgetとは何か
FlutterにおけるStatelessWidget
は、一度作成されるとその内部状態を変更できないウィジェットです。つまり、アプリの実行中にStatelessWidget
が再構築されるたびに、同じ設定で再構築されます。
StatelessWidget
は、ユーザーインターフェースの一部を他のウィジェットの集合体で記述するウィジェットです。これらのウィジェットは、ユーザーインターフェースをより具体的に記述します。この構築プロセスは、ユーザーインターフェースの記述が完全に具体的になる(つまり、具体的なRenderObject
を記述するRenderObjectWidget
で完全に構成される)まで再帰的に続けられます。
StatelessWidget
は、その外観とプロパティがウィジェットの寿命全体を通じて変わらないウィジェットです。つまり、StatelessWidget
はアプリの実行中に状態を変更できないため、アプリが動作している間にウィジェットを再描画することはできません。
StatelessWidget
は、その外観がオブジェクト自体の設定情報とウィジェットが膨らむBuildContext
以外の何ものにも依存しないユーザーインターフェースの部分を記述する場合に有用です。動的に変更できる構成が必要な場合、例えば内部の時計駆動状態を持つためや、システム状態に依存するためには、StatefulWidget
の使用を検討してください。
StatelessWidget
は、build
関数をoverride
(上書き)し、build
関数内で描画するWidget
を返すことで描画を行います。もし親Widget
でStatelessWidget
で使用した変数を変更した場合、子であるStatelessWidget
は全て再描画(build
)されます。
以上が、StatelessWidget
の基本的な説明です。具体的なコード例や使用例については、次の小見出しで詳しく説明します。
initStateとは何か
FlutterにおけるinitState
は、StatefulWidget
がウィジェットツリーに挿入されるときに一度だけ呼び出されるメソッドです。このメソッドは、StatefulWidget
の初期化時に呼び出され、通常はリスナーの登録などの初期化作業を行うためにオーバーライドされます。
initState
メソッドは、ウィジェットの初期化に関連するタスクを実行するためのコードを書くことが一般的です。以下は、initState
メソッド内に書くべき典型的なコードの例です:
@override
void initState() {
super.initState();
// 初期化と前準備
var myVariable = 0;
var myObject = MyClass();
myObject.addListener(_handleObjectChange);
// 非同期タスクの開始
_fetchData();
// ウィジェットの状態の更新
setState(() {
myVariable = 1;
});
}
@override
void dispose() {
// リソースの解放
myObject.removeListener(_handleObjectChange);
myObject.dispose();
super.dispose();
}
void _fetchData() async {
// 非同期タスクの実行
final result = await fetchData();
setState(() {
// ウィジェットの状態の更新
data = result;
});
}
void _handleObjectChange() {
// オブジェクトの変更イベントの処理
setState(() {
// ウィジェットの状態の更新
// ...
});
}
上記の例では、ウィジェットの初期化や前準備、非同期タスクの開始、ウィジェットの状態の更新、リソースの解放など、initState
メソッド内で行う一連の処理の例を示しています。
以上が、initState
の基本的な説明です。具体的なコード例や使用例については、次の小見出しで詳しく説明します。
StatelessWidgetでinitStateを使う方法
Flutterでは、StatelessWidget
は状態を持たないため、initState
メソッドを直接使用することはできません。しかし、StatefulWidget
のようなライフサイクルメソッドを必要とする場合でも、StatelessWidget
を使用したいという要件がある場合があります。
そのような場合には、カスタムのStatefulWidget
を作成し、その中でinitState
を使用することで、StatelessWidget
のように振る舞うウィジェットを作成することができます。以下に、その一例を示します:
class StatefulWrapper extends StatefulWidget {
final Function onInit;
final Widget child;
const StatefulWrapper({@required this.onInit, @required this.child});
@override
_StatefulWrapperState createState() => _StatefulWrapperState();
}
class _StatefulWrapperState extends State<StatefulWrapper> {
@override
void initState() {
if (widget.onInit != null) {
widget.onInit();
}
super.initState();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
上記のコードでは、StatefulWrapper
という新しいStatefulWidget
を作成しています。このウィジェットは、initState
メソッド内で実行する関数(onInit
)と、子ウィジェット(child
)を引数として受け取ります。
initState
メソッド内では、onInit
関数がnullでない場合にのみ、その関数を実行します。そして、build
メソッドでは、子ウィジェットをそのまま返すことで、StatelessWidget
のように振る舞います。
このStatefulWrapper
を使用することで、StatelessWidget
の中でinitState
のような処理を行うことができます。具体的な使用例については、次の小見出しで詳しく説明します。
StatefulWrapperクラスの作成
Flutterでは、StatelessWidget
でinitState
のようなライフサイクルメソッドを使用するために、カスタムのStatefulWidget
を作成することができます。以下に、その一例としてStatefulWrapper
クラスの作成方法を示します:
class StatefulWrapper extends StatefulWidget {
final Function onInit;
final Widget child;
const StatefulWrapper({@required this.onInit, @required this.child});
@override
_StatefulWrapperState createState() => _StatefulWrapperState();
}
class _StatefulWrapperState extends State<StatefulWrapper> {
@override
void initState() {
if (widget.onInit != null) {
widget.onInit();
}
super.initState();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
上記のコードでは、StatefulWrapper
という新しいStatefulWidget
を作成しています。このウィジェットは、initState
メソッド内で実行する関数(onInit
)と、子ウィジェット(child
)を引数として受け取ります。
initState
メソッド内では、onInit
関数がnullでない場合にのみ、その関数を実行します。そして、build
メソッドでは、子ウィジェットをそのまま返すことで、StatelessWidget
のように振る舞います。
このStatefulWrapper
を使用することで、StatelessWidget
の中でinitState
のような処理を行うことができます。具体的な使用例については、次の小見出しで詳しく説明します。
StatefulWrapperを使用した例
以下に、StatefulWrapper
を使用した具体的なコード例を示します:
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StatefulWrapper(
onInit: () {
_getThingsOnStartup().then((value) {
print('初回の処理が実行される!');
});
},
child: Scaffold(
appBar: AppBar(
title: Text('ホーム'),
),
body: Center(
child: Text('ほーむ'),
),
),
);
}
Future _getThingsOnStartup() async {
await Future.delayed(Duration(seconds: 2));
}
}
上記のコードでは、HomePage
というStatelessWidget
がStatefulWrapper
を使用しています。onInit
関数として、_getThingsOnStartup
という非同期関数を指定しています。この関数は、HomePage
が初めて描画されるときに一度だけ実行されます。
また、child
として、Scaffold
ウィジェットを指定しています。このScaffold
ウィジェットは、HomePage
の本体部分を表しています。
このように、StatefulWrapper
を使用することで、StatelessWidget
の中でinitState
のような処理を行うことができます。具体的な使用例については、次の小見出しで詳しく説明します。