Flutterの学習で詰まるポイント(2)Stateがわからないで、Sateは、Widgetのライフサイクルを表現したものだと説明しました。
Flutterが提唱しているWidgetのライフサイクルは、生成→初期化→変更→破棄で表現できます。図式化したのが、こちらの画像です。

setState
上記の図の右側に注目してください。ready→(強制的にウイジェットを再構築)→ setState → buildと書かれていると思います。setStateを呼び出すことで、buildを呼び出すことができます。
floatingActionButton: FloatingActionButton(
onPressed:() => setState( () => _counter++;),
tooltip: 'Increment',
child: const Icon(Icons.add),
),
setStateに引数も戻り値も持たない関数を代入して、関数の内部で自分が参照しているデータを更新します。そうすると、新しいデータでbuildが実行されます。build(1), build(2) というイメージを持つと、わかりやすいかもしれません。
カウンターアプリのコードにコメントをたくさん入れておくので、StatefulWidgetのコードを読めるようになってください。
import 'package:flutter/material.dart';
void main() {
// Flutterアプリが起動する時に呼ばれる関数。必ず実装する。
// runAppも必要。
runApp(const CounterAppWidget(title: 'CounterApp'));
}
/// [StatefulWidget]を継承したクラスを作ります。
class CounterAppWidget extends StatefulWidget {
const CounterAppWidget({required this.title, super.key});
/// AppBarのタイトルです
final String title;
/// createStateの実装が必須です
/// [CounterAppWidget]に紐づくStateが生成されます。
@override
State<CounterAppWidget> createState() => CounterAppState();
}
/// [CounterAppWidget]の状態管理をするためのStateを生成します。
class CounterAppState extends State<CounterAppWidget> {
int _counter = 0;
/// Widgetが初期化される時に呼び出したい処理を書きます
/// ここでは複雑になるので書きませんが、APIからデータを取って仕込む等が考えられます。
@override
void initState() {
super.initState();
}
// setStateが呼ばれると、buildメソッドが再実行されます。
// counterがインクリメントされた状態でbuildされますので、
// 1,2,3,4...とUIが更新されるという仕組みです。
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
),
);
}
}