BLOG
StatefulWidgetとStatelessWidgetの違い
1. はじめに
FlutterにはStateless(ステートレス)ウィジェットとStateful(ステートフル)ウィジェットの2つのタイプが存在します。これら2つのウィジェットは、Flutterでのすべてのウィジェットの基本要素です。
StatelessとStatefulを説明する前に、まずState(状態)の概念を理解する必要があります。Stateはウィジェット内で変化できる値やデータのことを指します。例えば、「いいね!」ボタンがある場合、そのボタンがクリックされたかどうかに応じて、ボタンの見た目が変わります。ボタンの状態は、塗りつぶされるか塗りつぶされないかの2つの状態に分かれます。したがって、ウィジェットが変化しない場合、それは状態を持たないと言えます。
Stateの概念を理解したら、StatelessとStatefulの名前の由来も理解しやすくなります。Statelessは「状態を持たない」ことを示し、Statefulは「状態を持つ」ことを示します。
StatelessWidgetは、そのウィジェット内のデータが変化しない静的なUIを構築するためのものです。例えば、タイトルが動的に変更されないボタンを作成したい場合、StatelessWidgetを使用してボタン用のウィジェットを作成できます。
2. StatefulWidgetとStatelessWidgetのご紹介
2.1. StatelessWidget
その名前が示す通り、StatelessWidgetは不変です。ユーザーの操作に対して変化しないため、内部で状態を保持しません。この種のウィジェットは、親ウィジェットの変更にのみ反応します。
StatelessWidgetは次の特徴を持ちます。
- イミュータブル(Immutable): StatelessWidgetは一度作成されると、その内部の状態を変更することはできません。ウィジェットがビルドされると、その内容は変わりません。
- 再描画の制御: StatelessWidgetは自動的に再描画されず、親ウィジェットが再描画する必要がある場合にのみ再描画されます。これは、データが変更されない限り、ウィジェットが不要に再描画されることを防ぎます。
- パフォーマンス向上: ウィジェットの状態が変わらないため、StatelessWidgetはパフォーマンスが向上し、軽量です。データの変更がない場合、再描画が不要なため、アプリケーションのパフォーマンスを向上させます。
伝統的な "Hello World "の例から始めましょう。
class MyHome extends StatelessWidget {
const MyHome({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("Stateless Widget Demo"),
),
body: const Center(
child: Text("Hello World"),
),
),
);
}
}
Flutter 3.13.6(Dart 3.1.3)で実施されています。
2.2 StatefulWidget
StatefulWidgetは、StatelessWidgetの逆です。つまり、ユーザーの操作に応じて動的に変化するUIを作成したい場合に使用します。例えば、ボタンをクリックするとアプリの背景色を変更したい場合、StatefulWidgetを利用できます。
StatefulWidgetは次の特徴を持ちます。
- ミュータブル(Mutable): StatefulWidgetは状態を持ち、その状態は変更可能です。ユーザーの入力や外部のデータに応じて状態を変更し、UIを更新できます。
- 再描画のトリガー: 状態が変化すると、StatefulWidgetはそれを検出し、自動的に再描画をトリガーします。これにより、ユーザーの操作に応じてUIが変化します。
- 動的なUIの構築: Statefulウィジェットを使用することで、動的なUIを構築できます。例えば、フォームの入力値を受け取り、それに応じてリアルタイムでUIを更新することができます。
- データの管理: Statefulウィジェットは状態を管理し、データの変更とUIの同期を取るのに役立ちます。これは、アプリケーション内でのデータのフローを管理するのに役立ちます。
StatefulWidgetは、StatelessWidgetを含むことができます。
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Stateful Widget Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Counter:',
style: TextStyle(fontSize: 20),
),
Text(
'$_counter',
style: const TextStyle(fontSize: 40),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
Flutter 3.13.6(Dart 3.1.3)で実施されています。
MyStatefulWidgetStateの内部で、カウンタ値を記録するためのプライベート変数「_counter」を宣言し、0に初期化します。また、ユーザがアプリと対話するときに呼び出されるプライベートメソッド「_incrementCounter」を定義します。呼び出されると、setStateメソッドを使用して「_counter」を更新し、ウィジェットの再構築をトリガします。
3. まとめ
StatelessWidgetとStatefulWidgetはFlutterの基本要素であり、これらを理解して活用することで、より良いコードを書き、優れたアプリケーションアーキテクチャを構築できます。