Flutter入門

【5分でわかる】Providerの使い方 | Flutter入門


ども、木村です。本業はデータサイエンティスト、副業でアプリ開発をしています。

本記事は、FlutterにおけるProviderの使い方を解説します。

想定読者
  • Providerがわからない方
  • Providerを使って状態管理をしたい方

今回のソースコードは以下で公開されています。

https://github.com/kimuson/provider_demo

Providerとは?

ProviderはFlutterで状態管理をしたいときに使用するライブラリです。

通常、Flutterで状態管理をしたい場合、StatefulWidget と State を使用して状態管理を行います。

そもそもStatefulWidgetについてわからない方は、少々理解が難しいと思うので以下の図解をご覧ください。

上記の通りStatefulWidget と Stateは1:1で紐づくため、Stateの情報を複数の画面で利用したい場合利用することができません。

そのため、画面が多ければ多いほど同じような冗長なソースを実装しなければならなくなり、保守性が非常に悪くなります。

そこでProviderが大きな役割を果たします。

Providerを使えば親Widgetで取得した内容を子Widgetに受け渡すことができます。

これにより一つのステート情報を複数の画面で使用できるようになります。

そして何よりソースコードが非常にシンプルになります。

ポイント
  • Providerとは、Flutterで状態管理をしたいときに使用するライブラリ
  • Providerを使うと一つのステート情報を複数の画面で使用できるようになる

Providerの使い方

今回はFlutterの初期プロジェクトがStatefulWidgetを使ったカウンターアプリになっていますので、こちらをProviderに変更する実装をして理解を深めていきたいと思います。

既存プロジェクトとの変更点を比較したい場合は、以下のGitHubのコミット差分を参照ください。

https://github.com/kimuson/provider_demo/commit/b3fdf66e9875fc6fae98f0ccabd8e18858f61f48

プロジェクトの作成

以下のコマンドで初期プロジェクトを作成します。

今回は「provider_demo」という名前でプロジェクトを作成します。

flutter create provider_demo

Providerの導入

pubspec.yamlにProvider導入の処理を追記しましょう。

dependencies:
   provider: ^6.0.2

追記したら以下のコマンドでライブラリを導入します。

flutter pub get

Providerの実装

状態管理する対象を実装する

今回状態管理の対象となるのは、何回ユーザーにボタンを押したのかのカウンターの情報になります。

そして同じファイルにユーザーがボタンを押下したらカウンターの変数に+1する処理も実装します。

今回は、CountProvider.dartというファイルを新規で作成します。

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

class CountProvider with ChangeNotifier {
  // 今回状態管理をする変数
  int counter = 0;
  //状態を変化させる処理(ボタンを押した時に実行される処理)
  void incrementCounter() {
    counter++;
    notifyListeners();
  }
}

上記ソースに出てくる重要な点を整理します。

with ChangeNotifier

変数の状態に変化があれば参照しているwidgetに画面再描画の通知を送ります。

notifyListeners();

一連の処理が終わったことをwidgetに伝え、画面再描画の通知を送ります。

Providerで管理しているステート情報を参照する

次にステート情報を参照してみましょう。

main.dartを以下のように書き換えてください。

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
        providers: [
          ChangeNotifierProvider<CountProvider>(
            create: (context) => CountProvider(),
          ),
        ],
        child: MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(),
        ));
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final CountProvider countProvider =
        Provider.of<CountProvider>(context, listen: true);
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo Home Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              countProvider.counter.toString(),
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: countProvider.incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

重要な処理
MultiProvider(
        providers: [
          ChangeNotifierProvider<CountProvider>(
            create: (context) => CountProvider(),
          ),
        ],
        child: MaterialApp(

上記の処理で、子ウィジェットへ指定したステート情報への参照を許可しています。

一点注意するべきことは、親widgetが許可されたステート情報のみ子widgetは情報を参照できるため、必ず親ウィジェットでこちらの処理を実装してください。

 final CountProvider countProvider =
        Provider.of<CountProvider>(context, listen: true);

参照したい子widgetでこちらの処理を実装することで、Providerのデータを受け取ることができます。

countProvider.counter.toString(),

counterはCountProvider.dartで定義したカウント情報の変数名ですね。

このように記載すれば個別のステート情報を参照することが可能です。

onPressed: countProvider.incrementCounter,

ボタンが押されたときはCountProvider.dartで定義したincrementCounterメソッドの処理がよばれて、ステート情報であるcounterが+1される処理を実行しています。

まとめ:Providerを使って保守性をあげよう!

今回はFlutterにおけるProviderの使い方を解説しました。

Providerを使えばコードの保守性が上がるので大変おすすめです。

ぜひこの機会に習得してみてください。

今回のソースコードは以下で公開されています。

https://github.com/kimuson/provider_demo

最新のFlutterの勉強方法 まとめ

Flutterを入門から実践レベルまで一通り学習できる方法をまとめました。

Flutterの勉強方法を知る

Flutterを動画で学習する

Flutterを書籍で学習する