riverpod_annotation入門

riverpodとは


Flutter開発における状態管理ライブラリです。
主に、グローバルな状態(アプリ全体で使うデータ)の管理に利用されます。

riverpod関連の用語


riverpodを利用する上で知っておいた方がいい用語を簡単に紹介します。

  • 状態:アプリ内の変化するデータ。例えば、いいねのカウント数やログイン状態など。
  • Notifier:状態を持ち、その状態を変化させることができる編集者みたいなもの。
  • Provider:Notifierや状態にアクセスするための窓口みたいなもの。
import 'package:flutter_riverpod/flutter_riverpod.dart';

/// int型の状態(カウント)を管理する Notifier クラス
class CounterNotifier extends StateNotifier<int> {
  CounterNotifier() : super(0); // 初期値は 0

  void increment() => state++;  // カウントを +1
}

/// Notifier を使う Provider の定義
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
  return CounterNotifier();
});
  • ref:Providerにアクセスするためのカギみたいなもの。StatelessWidgetやStatefulWidgetはrefを持つことができないので、Providerで囲まれた状態を監視したり変更したりできない。
    • ref.watch:状態の変更を監視。状態が変更されたらUIを更新。
    • ref.read:状態を変更(状態を一度だけ取得もできる)。
    • ref.listen:状態の変更を監視。状態が変更されたら特定の処理を実行。
  • ConsumerWidget:refを使うことでProviderの中の状態を知ることができるウィジェット。
// ConsumerWidgetのbuild関数内で定義

// watchで状態を監視
final count = ref.watch(counterProvider);

return Column(
  children: [
    Text('カウント: $count'), // ✅ ここが再描画される
    
    // readで状態を変更
		ElevatedButton(
		  onPressed: () {
			  ref.read(counterProvider.notifier).increment()
			  // watchしているのでcountを表示している部分が再描画される
		  },
		  child: Text('+1'),
		),
  ],
);

riverpod_annotationとは


シンプルなコードを書くことで、NotifierやProviderを自動生成してくれる便利なパッケージです。

pubspec.yaml


riverpod_annotationを使う上で追加する必要のあるパッケージです。

dependencies:
	flutter:
	flutter_riverpod:
	riverpod_annotation: # アノテーション(@で始まる特別な目印)の定義
dev_dependencies:
	build_runner: # 生成処理を実行するツール
	riverpod_generator: # @riverpod を使ったコードから .g.dart を自動生成する

実装:事前知識


  • 同期処理(Future・Stream以外)の状態の場合はNotifier, NotifierProviderを生成
  • 非同期処理(Future・Stream)の状態の場合は、AsyncNotifier, AsyncNotifierProviderを生成
    • riverpod1系よりシンプルな構成になりました。

実装:同期処理


counter_provider.dart

import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'counter_provider.g.dart'; // ファイル名.g.dartを作ってくれる

@riverpod
class Counter extends _$Counter {
  @override
  int build() => 0; // 初期値を返す

  void increment() => state++; // 状態を+1
  
}

counter_provider.g.dart 生成コマンド

flutter pub run build_runner build --delete-conflicting-outputs

ConsumerWidgetでの使い方は同じです。

// ConsumerWidgetのbuild関数内で定義

// watchで状態を監視
final count = ref.watch(counterProvider);

return Column(
  children: [
    Text('カウント: $count'), // ✅ ここが再描画される
    
    // readで状態を変更
		ElevatedButton(
		  onPressed: () {
			  ref.read(counterProvider.notifier).increment()
			  // watchしているのでcountを表示している部分が再描画される
		  },
		  child: Text('+1'),
		),
  ],
);

実装:非同期処理


user_name_provider.dart

import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'user_name_provider.g.dart';

@riverpod
class UserName extends _$UserName {
  @override
  Future<String> build() async {
    await Future.delayed(const Duration(seconds: 1)); // 疑似API呼び出し
    return 'John';
  }
}

user_name_provider.g.dart 生成コマンド

flutter pub run build_runner build --delete-conflicting-outputs

ConsumerWidget 内

// ConsumerWidgetのbuild関数内で定義

// 状態を監視
final user = ref.watch(userNameProvider);

// 状態を3つのパターンに分けて表示
// data:状態を取得済
// loading:状態を取得中
// error:状態の取得に失敗(e:エラー内容, s:エラー発生箇所)
return user.when(
  data: (name) => Text('こんにちは、$name'),
  loading: () => CircularProgressIndicator(),
  error: (e, s) => Text('エラー: $e'),
);

まとめ


  • riverpod_annotation は、ProviderやNotifierの定義を簡潔に書くためのアノテーションパッケージです。
  • @riverpod などのアノテーションを使うことで、状態管理のためのProviderやNotifierを自動生成できます。
  • グローバルな状態だけでなく、非同期処理や引数付き(family)のProviderにも対応。
  • 実際の自動生成は riverpod_generator + build_runner によって行われます。

参考

あわせて読みたい