🐷
[Flutter]StatelessWidgetとStatefulWidget
- WidgetはStatelessWidgetかStatefulWidgetかのどちらかに属するよ
- Statelessは変化しないWidgetだよ
- Statefulは変化するWidgetだよ。ユーザーのインタラクションに応じて変化するよ。例えばRadio、Checkboxとかがそれにあたるよ
- Widgetの状態はStateというオブジェクトに格納されて、外観とは分離して管理されるよ
- Stateでは変化対象の値を持ち、変化を通知する
setState
メソッドを持つよ -
setState
が呼び出されると、フレームワークが対象のStatefulWidgetを再描画するよ
StatefulWidgetをつくる
- 自分で独自のStatefulWidgetをつくることができるよ
- このとき、作るものが2つあるよ
- StatefulWidgetを継承したクラス
- Stateを継承したクラス
StatefulWidgetクラス
- StatefulWidgetを継承したクラスを定義するよ
- StatefulWidgetには
createState
というメソッドがあり、overrideするよ -
createState()
はStateオブジェクトを返すよ - nextでいう、
useState
にあたる気がするよ
class FavoriteWidget extends StatefulWidget {
_FavoriteWidgetState createState() => _FavoriteWidgetState();
}
Stateクラス
- Stateを継承したクラスを定義するよ
- 継承するとき、StateクラスにGenericで自分で作成したStatefulWidgetを指定するよ
- Stateで管理したい値をインスタンス変数で持つよ
- Stateは
build
メソッドを持つのでoverrideしてUIを定義するよ - この中ではStateの値にアクセスできるよ
class _FavoriteWidgetState extends State<FavoriteWidget> {
bool _isFavorited = true;
int _favoriteCount = 41;
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: EdgeInsets.all(0),
child: IconButton(
padding: EdgeInsets.all(0),
alignment: Alignment.centerRight,
icon: (_isFavorited ? Icon(Icons.star) : Icon(Icons.star_border)),
color: Colors.red[500],
onPressed: _toggleFavorite,
),
),
SizedBox(
width: 18,
child: Container(
child: Text('$_favoriteCount'),
),
),
],
);
}
}
- さらにStateの値を変更するメソッドを追加してみるよ
void _toggleFavorite() {
setState(() {
if (_isFavorited) {
_favoriteCount -= 1;
_isFavorited = false;
} else {
_favoriteCount += 1;
_isFavorited = true;
}
});
}
- setStateメソッドを呼び出して、そのなかでStateの値を変更するよ
- そうすると変更された値でStatefulWidgetが再描画されるよ
- このように状態を持つWidgetを独自に定義して、ユーザーの操作に応じて状態を変更していくことで、インタラクティブなアプリを作っていくことができるよ
Discussion