[Flutter] 状態管理:Provider の使い方

Flutterにおける状態管理は、アプリケーションの成長に伴って複雑になることがよくあります。この問題を解決するために、Flutterコミュニティは様々な状態管理のパターンを提供しています。その中でも、Flutter Providerパッケージは、非常にシンプルで使いやすい状態管理の方法として人気があります。

目次

Providerとは何ですか?

Providerは、Flutterアプリケーションで状態を管理するためのパッケージです。このパッケージは、アプリケーション全体で状態を共有するためのシンプルで効率的な方法を提供します。Providerは、InheritedWidgetを使用して状態を共有し、変更された状態を子ウィジェットに通知することができます。

Providerの使い方

Flutter Providerを使うには、まずパッケージをインストールする必要があります。pubspec.yamlファイルに以下のように追加します。

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.0

Providerを使用するには、以下の手順に従います。

Modelクラスを作成する

まず、状態を保持するためのModelクラスを作成します。これは、普通のDartクラスです。

class CounterModel extends ChangeNotifier {
  int _counter = 0;

  int get counter => _counter;

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

上記の例では、CounterModelクラスが作成されています。このクラスは、現在のカウンターの値を保持します。incrementCounter()メソッドを呼び出すと、カウンターの値がインクリメントされ、変更通知が発生します。

Providerを使用してModelを提供する

次に、CounterModelオブジェクトを提供するために、Providerを使用します。Providerは、buildメソッド内で使用することができます。以下のように、Providerを使用してCounterModelオブジェクトを提供することができます。

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => CounterModel(),
      child: MaterialApp(
        home: HomeScreen(),
      ),
    );
  }
}

上記の例では、ChangeNotifierProviderを使用してCounterModelオブジェクトを提供しています。createプロパティには、新しいCounterModelオブジェクトを作成する無名関数を指定します。この無名関数は、Providerが作成されるときに一度だけ実行されます。

モデルを使用する

最後に、CounterModelオブジェクトを使用してUIをビルドします。これは、Providerを使用してCounterModelオブジェクトを取得することで行います。以下の例では、Consumerウィジェットを使用して、CounterModelオブジェクトを取得し、UIをビルドしています。

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Provider Example'),
      ),
      body: Center(
        child: Consumer<CounterModel>(
          builder: (context, counterModel, child) => Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                'Counter Value: ${counterModel.counter}',
                style: TextStyle(fontSize: 24),
              ),
              SizedBox(height: 16),
              ElevatedButton(
                onPressed: () {
                  counterModel.incrementCounter();
                },
                child: Text('Increment'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

上記の例では、Consumerウィジェットが使用されています。Consumerウィジェットは、変更されたデータを監視し、必要に応じてUIを再ビルドすることができます。CounterModelクラスのインスタンスを取得するには、Consumerウィジェットを使用し、builder関数を定義します。builder関数は、新しいUIをビルドするために使用されます。

Flutter Providerの便利な機能

Flutter Providerには、以下のような便利な機能が含まれています。

MultiProvider

MultiProviderは、複数のProviderを1つの親ウィジェットでラップするために使用されます。例えば、以下のように使用することができます。

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

void main() {
  runApp(MyApp());
}

class CounterModel with ChangeNotifier {
  int _counter = 0;

  int get counter => _counter;

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

class UserModel with ChangeNotifier {
  String _name = '';

  String get name => _name;

  set name(String value) {
    _name = value;
    notifyListeners();
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<CounterModel>(
          create: (context) => CounterModel(),
        ),
        ChangeNotifierProvider<UserModel>(
          create: (context) => UserModel(),
        ),
      ],
      child: MaterialApp(
        title: 'Flutter Provider Example',
        home: HomeScreen(),
      ),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Provider Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Consumer<CounterModel>(
              builder: (context, counterModel, child) {
                return Text(
                  'Counter Value: ${counterModel.counter}',
                  style: TextStyle(fontSize: 24),
                );
              },
            ),
            Consumer<UserModel>(
              builder: (context, userModel, child) {
                return Text(
                  'User Name: ${userModel.name}',
                  style: TextStyle(fontSize: 24),
                );
              },
            ),
            ElevatedButton(
              onPressed: () {
                Provider.of<CounterModel>(context, listen: false)
                    .incrementCounter();
                Provider.of<UserModel>(context, listen: false).name =
                    'John Doe';
              },
              child: Text('Increment & Set Name'),
            ),
          ],
        ),
      ),
    );
  }
}

上記のコードでは、CounterModelUserModelの両方がChangeNotifierを継承しており、incrementCounter()メソッドやnameプロパティを持っています。MyAppクラスでは、MultiProviderを使用して両方のモデルを提供し、HomeScreenウィジェットで利用します。

HomeScreenのビルドメソッドでは、Consumerウィジェットを使用して、CounterModelUserModelの変更を監視しています。それぞれのbuilder関数内で、モデルの値を取得してUIを構築しています。また、ElevatedButtonが押されたときに、CounterModelのカウンターをインクリメントし、UserModelの名前を設定しています。

ProxyProvider

ProxyProviderは、1つのProviderから別のProviderを作成するために使用されます。以下のように使用することができます。

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

void main() {
  runApp(MyApp());
}

class CounterModel with ChangeNotifier {
  int _counter = 0;

  int get counter => _counter;

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

class UserModel {
  String _name = '';

  String get name => _name;

  set name(String value) {
    _name = value;
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<CounterModel>(
          create: (context) => CounterModel(),
        ),
        ProxyProvider<CounterModel, UserModel>(
          update: (context, counterModel, userModel) =>
              UserModel()..name = 'John Doe',
        ),
      ],
      child: MaterialApp(
        title: 'Flutter Provider Example',
        home: HomeScreen(),
      ),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Provider Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Consumer<CounterModel>(
              builder: (context, counterModel, child) {
                return Text(
                  'Counter Value: ${counterModel.counter}',
                  style: TextStyle(fontSize: 24),
                );
              },
            ),
            Consumer<UserModel>(
              builder: (context, userModel, child) {
                return Text(
                  'User Name: ${userModel.name}',
                  style: TextStyle(fontSize: 24),
                );
              },
            ),
            ElevatedButton(
              onPressed: () {
                Provider.of<CounterModel>(context, listen: false)
                    .incrementCounter();
              },
              child: Text('Increment Counter'),
            ),
          ],
        ),
      ),
    );
  }
}

このコードでは、CounterModelUserModelを定義し、ChangeNotifierを継承しています。CounterModelはカウンターの状態を管理し、incrementCounter()メソッドを提供しています。UserModelはユーザーの名前を管理する単純なモデルです。

MyAppクラスでは、MultiProviderを使用して複数のプロバイダーを提供します。ChangeNotifierProviderを使用してCounterModelを提供し、ProxyProviderを使用してCounterModelからUserModelを生成します。updateコールバック内で新しいUserModelインスタンスを作成し、名前を設定しています。

HomeScreenのビルドメソッドでは、Consumerウィジェットを使用してCounterModelUserModelの変更を監視します。CounterModelのカウンターとUserModelの名前を表示し、ElevatedButtonが押されるとCounterModelのカウンターをインクリメントします。

まとめ

Flutter Providerは、Flutterアプリケーションで状態を管理するための非

常に手軽で強力なツールです。ChangeNotifierProviderを使用して、モデルクラスを提供することができ、Consumerウィジェットを使用して、変更を監視し、必要に応じてUIを再ビルドすることができます。また、MultiProviderを使用して複数のProviderを1つの親ウィジェットでラップすることができ、ProxyProviderを使用して1つのProviderから別のProviderを作成することができます。

Flutter Providerは、簡単に導入でき、状態管理を簡単に実装できるため、Flutterアプリケーションの開発には必要不可欠なツールです。是非、今後の開発に取り入れてみてください。

Provider以外の状態管理の方法は以下のページおよび、ページ内リンクの記事で詳しく説明していますので、参考にしてみて下さい。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次