【Flutter】provider で状態管理するサンプルを作ったので紹介【初心者向け】

どーも、ぐるたか@guru_takaです。

Flutterのパッケージ『provider』を使って、状態管理するサンプルを作ったので紹介します。+ボタンを押すと、真ん中の数字がカウントされるアプリです。

ソースはGithubにあげています。参考になれば幸いです。
参考 gurutaka/provider_sampleGithub

ソース

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ChangeNotifierProvider(
        create: (context) => Counter(),
        child: MyHomePage(),
      ),
    );
  }
}

class Counter with ChangeNotifier {
  int _value = 0;
  int get value => this._value;

  _increment() {
    _value++;
    notifyListeners();
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("First Flutter Provider Example"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            WidgetCenterText(),
            WidgetNumText(),
          ],
        ),
      ),
      floatingActionButton: WidgetIncrementBtn(),
    );
  }
}

class WidgetIncrementBtn extends StatelessWidget {
  const WidgetIncrementBtn({Key key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    final counter = Provider.of(context, listen: false);
    return FloatingActionButton(
      onPressed: () => counter._increment(),
      tooltip: 'Increment',
      child: Icon(Icons.add),
    );
  }
}

class WidgetNumText extends StatelessWidget {
  const WidgetNumText({Key key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Consumer(
      builder: (context, counter, _) {
        return Text(
          '${counter.value}',
          style: Theme.of(context).textTheme.headline,
        );
      },
    );
  }
}

class WidgetCenterText extends StatelessWidget {
  const WidgetCenterText({Key key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Text('You have pushed the button this many times:');
  }
}

準備

パッケージ『provider』を導入しましょう。

pubspec.yaml
//追記
dependencies:
  provider: ^4.0.5+1
コマンドライン
$ flutter pub get
参考 providerpub.dev

簡単な解説

 Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
     home: ChangeNotifierProvider(
        create: (context) => Counter(),
        child: MyHomePage(),
      ),
    );
  }

~~~~~~~~~~~~~
~~~~~~~~~~~~~

class Counter with ChangeNotifier {
  int _value = 0;
  int get value => this._value;

  _increment() {
    _value++;
    notifyListeners();
  }
}

~~~~~~~~~~~~~
~~~~~~~~~~~~~

class WidgetNumText extends StatelessWidget {
  const WidgetNumText({Key key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Consumer(
      builder: (context, counter, _) {
        return Text(
          '${counter.value}',
          style: Theme.of(context).textTheme.headline,
        );
      },
    );
  }
}

ChangeNotifierProviderを使い、親から子孫に対してChangeNotifierを内包したCounterクラスを渡します。

このとき、notifyListeners();によって、変更されたことをお知らせし、リビルドされる感じです!

あとはProvider.of(context)で、Counterクラスのメソッドや変数が使えます。

また、第2引数にlisten: falseを入れれば、リビルドを防止。今回は、+ボタンはリビルドの必要性がないため、listen: falseを引数に入れてます。

Consumerは状態の変化が通知されると、自動でリビルドしてくれる優れものです!

参考リンク

参考 Provider のススメUnselfish Meme 参考 【Flutter】 package:provider の各プロバイダの詳細Qiita 参考 【Flutter】【Pragmatic State Management in Flutter (Google I/O'19)】で推奨されてたProvider使ってみたQiita

コメントを残す