Skip to Content
ドキュメントFlutterコース状態管理を理解する

状態管理を理解する(setState / Provider)

このページで学ぶこと

  • StatefulWidgetsetState で状態を管理できる
  • 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('リセット'),
            ),
          ],
        ),
      ),
    );
  }
}
dart

ポイント

  • _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 さん!'),
          ],
        ),
      ),
    );
  }
}
dart

Provider — 複数ページをまたいだ状態管理

setState は単一のWidget内の状態管理に使います。
複数のページで共有する状態(ログインユーザー・カートの中身など)には Provider が便利です。

インストール

flutter pub add provider
bash

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();
  }
}
dart

② アプリ全体に 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(),
    ),
  );
}
dart

③ どこからでも状態を使う

// 状態を読むだけ
final count = context.watch<CounterProvider>().count;
 
// 状態を変更する(再描画は不要)
context.read<CounterProvider>().increment();
dart

確認しよう

  • StatefulWidgetsetState でカウンターを作れた
  • TextEditingController でテキスト入力を処理できた
  • Provider をインストールして ChangeNotifier を作れた

AIに聞いてみよう

「Flutterの状態管理でRiverpodとProviderはどちらを使うべきですか?初心者に向けた違いを教えてください」


次のステップ

画面遷移を実装しよう

Last updated on