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のような処理を行うことができます。具体的な使用例については、次の小見出しで詳しく説明します。