本記事は、マルチプラットフォーム開発のSDK【Flutter】を用いたモバイルアプリ開発入門の為の記事です。
Flutterアプリの開発で最初に目にする【StatefulWidget】。このStatefulWidgetは、クラスが2つに分かれています。本記事ではこの理由について解説していきます。
StatefulWidgetについて復習
はじめに、StatefulWidgetで特徴的な部分に関して復習をしておきます。
- 親Widgetから不変の値を受け取る場合、finalを宣言する
- コンストラクターで変数に値を設定
- Stateクラスをインスタンス化する
- Stateクラスで変数の値を更新する際、setStateを呼ぶ
- 画面に描画するWidgetを返すbuild関数を作成する
- 親Widgetで受け取った変数にアクセスする場合、widget.変数名を用いる
サンプルとして、以下にコードを上げておきます。
class MyHomePage extends StatefulWidget {
// ➀親Widgetから受け取る変数の値が不変の場合、final変数として宣言する。
// finalが宣言された変数はWidgetが作成される際(実行時)に値が適応され、それ以降値の変更は不可能となる。
final String title;
// ➁コンストラクター。クラス名({this.変数名})とすることで自動的に渡された親Widgetから渡された値を変数に設定する
MyHomePage({Key key, this.title}) : super(key: key);
// ➂ステートクラスをインスタンス化する。
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
// ➃変数の値を変更する際、setStateを必ず呼ぶ必要がある
setState(() => _counter++);
}
// ➄描画するWidgetを返すbuild関数を定義する
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// ➅StatefulWidgetから受け取った値をState側で使う場合、widget.変数名を用いる
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('$_counter'),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
StatefulWidgetの構成
上記のコードからも分かる通り、Stateful WidgetはStatefulWidgetを継承したMyHomePageと、Stateを継承した_MyHomePageStateの2種類から構成されています。
ここで、2つの疑問が浮かびます。
- なぜStatefulWidgetは2つに分かれているのか
- StateがState<StatefulWidget名>を継承しているのはなぜか
➀なぜStatefulWidgetは2つに分かれているのか
StatefulWidgetは不変であるWidgetを継承しています。よって、StatefulWidget自体は不変である必要があります。
しかし、StatefulWidgetは可変である必要があるため、そこで登場するのがStateです。Stateに可変の要素を持たせています。
Flutter SDKはStatefulWidgetを何度も再作成することができ、それに対しStateは1度だけ作成されます。
そして、再作成されたStatefulWidgetは既に作成されているStateを参照することで、Widgetの再作成(画面の描画)を効率的に行うことができます。
➁StateがState<StatefulWidget名>を継承しているのはなぜか
State側でStatefulWidgetで定義した変数にアクセスできるようにするためです。
StateクラスはStatefulWidgetが親Widgetから渡された変数にアクセスすることができます。
その時、上記の【StatefulWidgetの復習】で解説したようにwidget.変数名
と表記します。
このような形でアクセスするためには、そのStateが参照しているStatefulWidgetの型は何かを定義することが必要です。
よって、State<StatefulWidget名>とすることでStatefulWidgetが持つ変数を、Stateが識別することができます。
最後に
本記事では、Flutterアプリの開発に際し多く使う機会があるStateful Widgetの構成について解説しました。
このように、Flutterではアプリのパフォーマンスが効率的に行われるように随所に配慮がされています。
そもそもStatefulWidgetとは何??という方は、以下の記事も参考にしていただければと思います。
参考
以下のStack overflowを参考にさせていただきました。