状態管理を理解する(setState / Provider)
このページで学ぶこと
StatefulWidgetとsetStateで状態を管理できる- Provider パッケージで複数ページをまたいだ状態管理ができる
StatefulWidget と setState
前のページで StatelessWidget を学びました。
ユーザーの操作に反応してUIを変えたいときは StatefulWidget を使います。
カウンターを作る
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: CounterPage());
}
}
// StatefulWidget のテンプレート
class CounterPage extends StatefulWidget {
const CounterPage({super.key});
@override
State<CounterPage> createState() => _CounterPageState();
}
// 状態(State)を持つクラス
class _CounterPageState extends State<CounterPage> {
int _count = 0; // 状態変数(_ は プライベートを表す慣習)
void _increment() {
setState(() {
// setState() の中で状態を変更すると、buildが再実行される
_count++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('カウンター')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('$_count', style: const TextStyle(fontSize: 64)),
const SizedBox(height: 24),
ElevatedButton(
onPressed: _increment,
child: const Text('+1'),
),
TextButton(
onPressed: () => setState(() => _count = 0),
child: const Text('リセット'),
),
],
),
),
);
}
}ポイント
_countなどのアンダースコアから始まる変数はプライベート(Dartの慣習)setState()を呼ばないと画面が更新されないsetState()の中で状態を変更する
フォームを作る
class _FormPageState extends State<FormPage> {
// TextEditingController でテキストフィールドの値を管理する
final _nameController = TextEditingController();
String _submitted = '';
@override
void dispose() {
// メモリリークを防ぐため、不要になったら破棄する
_nameController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('フォーム')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
TextField(
controller: _nameController,
decoration: const InputDecoration(
labelText: '名前',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
setState(() {
_submitted = _nameController.text;
});
},
child: const Text('送信'),
),
if (_submitted.isNotEmpty)
Text('こんにちは、$_submitted さん!'),
],
),
),
);
}
}Provider — 複数ページをまたいだ状態管理
setState は単一のWidget内の状態管理に使います。
複数のページで共有する状態(ログインユーザー・カートの中身など)には Provider が便利です。
インストール
flutter pub add provider
flutter pub addは npm install に相当するコマンドです。
Provider の基本的な使い方
① 状態を管理するクラスを作る
// lib/providers/counter_provider.dart
import 'package:flutter/foundation.dart';
class CounterProvider extends ChangeNotifier {
int _count = 0;
int get count => _count; // ゲッター
void increment() {
_count++;
notifyListeners(); // 変更を通知 → 関連するWidgetが再描画される
}
void reset() {
_count = 0;
notifyListeners();
}
}② アプリ全体に Provider を提供する
// lib/main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'providers/counter_provider.dart';
void main() {
runApp(
// ChangeNotifierProvider でアプリ全体を囲む
ChangeNotifierProvider(
create: (_) => CounterProvider(),
child: const MyApp(),
),
);
}③ どこからでも状態を使う
// 状態を読むだけ
final count = context.watch<CounterProvider>().count;
// 状態を変更する(再描画は不要)
context.read<CounterProvider>().increment();確認しよう
-
StatefulWidgetとsetStateでカウンターを作れた -
TextEditingControllerでテキスト入力を処理できた - Provider をインストールして
ChangeNotifierを作れた
AIに聞いてみよう
「Flutterの状態管理でRiverpodとProviderはどちらを使うべきですか?初心者に向けた違いを教えてください」
次のステップ
Last updated on