【Flutter/Riverpod】StateNotifierProviderで状態管理|外部からデータ変更可能

今回はRiverpodのStateNotifierProviderを使った状態管理を行なっていきます。

StateNotifierProviderを使用するにはStateNotifierを継承したクラスを定義する必要があります。StateNotifierProviderでは直近のデータ(状態)を元に新しいデータを生成できます。

\ 世界最大級のオンライン学習サービス /

目次

事前準備|flutter_riverpodの導入

flutter pub add flutter_riverpod
import 'package:flutter_riverpod/flutter_riverpod.dart';

flutter_riverpodを導入します。

ProviderScopeでウィジェットツリーをラップ

void main() => runApp(ProviderScope(child: MyApp()));

Riverpodのプロバイダを使用するにはProviderScopeでウェジェットツリーのルート(先祖)となるWidgetをラップする必要があります。

StateNotifierProviderの使い方

StateNotifierを継承したクラスの定義

class Counter extends StateNotifier<int> {
  Counter() : super(0);

  void increment() => state++;
  void decrement() => state--;
}

まずはStateNotifierを継承したクラスを定義します。

コンストラクタでStateNotifierを継承する際に指定した型の初期値を渡します。今回はシンプルにint型の値を初期値とします。

StateNotifierProviderの定義

final counterProvider = StateNotifierProvider(
  (ref) => Counter(),
);

StateNotifierProviderStateNotifierを継承したクラスを返り値に取ります。

今回はグローバル変数として定義しています。(記事下にサンプルコードあり)

データ取得

class MyApp extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('FlutterZero')),
        body: Center(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              IconButton(
                icon: Icon(Icons.remove),
                onPressed: () => ref.read(counterProvider.notifier).decrement(),
              ),
              Text(
                count.toString(),
                style: TextStyle(fontSize: 30),
              ),
              IconButton(
                icon: Icon(Icons.add),
                onPressed: () => ref.read(counterProvider.notifier).increment(),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

StatelessWidgetでプロバイダの値を取得したい場合はConsumerWidgetを継承します。StatefulWidgetの場合はConsumerStatefulWidgetを継承します。

final count = ref.watch(counterProvider);

ref.watchStateNotifierProviderの値(ステート)を取得します。

外部からデータを変更

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    IconButton(
      icon: Icon(Icons.remove),
      onPressed: () => ref.read(counterProvider.notifier).decrement(),
    ),
    Text(
      count.toString(),
      style: TextStyle(fontSize: 30),
    ),
    IconButton(
      icon: Icon(Icons.add),
      onPressed: () => ref.read(counterProvider.notifier).increment(),
    ),
  ],
),

StateNotifierを継承したクラスのメソッドを使用して値(ステート)を変更できます。

Consumerでデータ取得

ConsumerWidgetまたはConsumerStatefulWidgetを継承せずにConsumerで値を取得することも可能です。

サンプルコード

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

class Counter extends StateNotifier<int> {
  Counter() : super(0);

  void increment() => state++;
  void decrement() => state--;
}

final counterProvider = StateNotifierProvider(
  (ref) => Counter(),
);

void main() => runApp(ProviderScope(child: MyApp()));

class MyApp extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('FlutterZero')),
        body: Center(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              IconButton(
                icon: Icon(Icons.remove),
                onPressed: () => ref.read(counterProvider.notifier).decrement(),
              ),
              Text(
                count.toString(),
                style: TextStyle(fontSize: 30),
              ),
              IconButton(
                icon: Icon(Icons.add),
                onPressed: () => ref.read(counterProvider.notifier).increment(),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

一緒に読みたい

参考

  • URLをコピーしました!
目次