0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Flutterの状態管理

Posted at

概要

Flutter では、アプリの UI を宣言的に構築するため、状態(State)を適切に管理しないと、

  • 画面遷移時にデータが消える
  • UI の更新が適切に行われない
  • データの一貫性が保てない

といった問題が発生します。筆者はFlutterを最近触り始めたペーペーなため、学習始めで特にこんがらがりそうな状態管理についてまとめておこうと思います。


状態管理とは?

状態管理(State Management) とは、アプリのデータ(状態)を適切に管理し、必要なときに UI へ反映させる仕組みのことです。

例えば、以下のようなデータは「状態」として扱います:

  • カウンターの値
  • API から取得したデータ
  • フォームの入力値
  • ログイン情報
  • ダークモードの ON/OFF

Flutter では、宣言的 UI を採用しているため、状態が変更されると UI の再描画が必要になります。そのため、適切な状態管理の手法を選択することが重要になります。


状態管理の分類

状態管理の手法は、大きく 2 つのカテゴリに分かれます。

  1. 単純な状態管理 Ephemeral State(画面内で完結する状態)

    • setState()
    • InheritedWidget / InheritedModel
    • ChangeNotifier + Provider
  2. グローバルな状態管理 App State(アプリ全体で共有する状態)

    • Provider
    • Riverpod
    • Bloc / Cubit
    • Redux
    • GetX

この分類を理解したうえで、どの方法を選ぶべきか検討する必要があります。


1. 単純な状態管理

setState()

setState() は、StatefulWidget 内で使用される最も基本的な状態管理手法です。

例:カウンターアプリ

class CounterScreen extends StatefulWidget {
  @override
  _CounterScreenState createState() => _CounterScreenState();
}

class _CounterScreenState extends State<CounterScreen> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Counter App")),
      body: Center(child: Text("Counter: $_counter")),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        child: Icon(Icons.add),
      ),
    );
  }
}

メリット・デメリット

✅ シンプルで理解しやすい
✅ 追加のパッケージが不要
setState() を呼ぶたびに StatefulWidget 全体が再描画される
❌ アプリが複雑になると管理が難しくなる

ChangeNotifier + Provider

Flutter 公式が推奨する状態管理の方法。ChangeNotifier は、状態変更を通知するクラスで、Provider は依存関係を管理するパッケージ。

例:Provider を使ったカウンターアプリ

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => CounterModel(),
      child: MyApp(),
    ),
  );
}

class CounterModel extends ChangeNotifier {
  int _counter = 0;
  int get counter => _counter;

  void increment() {
    _counter++;
    notifyListeners();
  }
}

class CounterScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Provider Counter")),
      body: Center(
        child: Text("Counter: ${context.watch<CounterModel>().counter}"),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => context.read<CounterModel>().increment(),
        child: Icon(Icons.add),
      ),
    );
  }
}

メリット・デメリット

setState() よりも適切に状態を管理できる
✅ パフォーマンスが良い(変更があった部分のみ更新)
❌ 小規模なアプリにはオーバースペックになることも


2. グローバルな状態管理

Riverpod

Flutter 公式が開発した最新の状態管理ライブラリ。Provider の進化版。

例:Riverpod を使ったカウンターアプリ

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final counterProvider = StateProvider<int>((ref) => 0);

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CounterScreen(),
    );
  }
}

class CounterScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final counter = ref.watch(counterProvider);
    return Scaffold(
      appBar: AppBar(title: Text("Riverpod Counter")),
      body: Center(child: Text("Counter: $counter")),
      floatingActionButton: FloatingActionButton(
        onPressed: () => ref.read(counterProvider.notifier).state++,
        child: Icon(Icons.add),
      ),
    );
  }
}

メリット・デメリット

✅ グローバルな状態管理が簡単
Provider よりも DI(依存関係管理)がしやすい
❌ シンプルなアプリにはオーバースペック


まとめ

状態管理手法 用途 規模
setState() 単純な状態管理 小規模
Provider 公式推奨 中規模
Riverpod 依存関係管理が楽 中大規模

アプリの規模や設計に応じて使い分けるのが最も重要ですが公式も推奨しているようなので、Riverpodを学んでおいて損はないかな?

RiverpodはRiverpodではまりどころがあるようなので、さらに調査を進めたいと思います。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?