💬

riverpodは ProviderObserverで状態を追跡しよう!

2024/08/05に公開

Flutter で開発をするとき、riverpodを使うプロジェクトはかなり多いのではないでしょうか。
本日は、Providerの生成や破棄、状態の変化の追跡について書いていこうと思います。

こんな人におすすめ

・riverpodをつかっている
・providerが生成、破壊されるタイミングを追跡したい

⭐️ loggerでproviderの状態を追跡できるようになります。

ProviderObserverとは

ProviderObserver は、Riverpodの機能の一つであり、Providerの状態変化を監視するために使用されます。これにより、プロバイダのライフサイクルイベント(読み込み、値の更新、削除など)を監視し、デバッグやロギングを行うことができます。
https://riverpod.dev/docs/concepts/provider_observer

以下の2つのsharedPreferencesProvider を比較してみましょう。

💡 リバーポッドのアノテーションの違いです!

① 短命な生存戦略

@riverpod
SharedPreferencesRepository sharedPreferencesRepository(
  SharedPreferencesRepositoryRef ref,
) {
  final sharedPreferences = ref.read(sharedPreferencesProvider);
  return SharedPreferencesRepositoryImpl(sharedPreferences);
}

② シングルトン生存戦略

※単一の依存のインスタンスが複数のクラスで共有されるパターン

@Riverpod(keepAlive: true)
SharedPreferencesRepository sharedPreferencesRepository(
  SharedPreferencesRepositoryRef ref,
) {
  final sharedPreferences = ref.watch(sharedPreferencesProvider);
  return SharedPreferencesRepositoryImpl(sharedPreferences);
}

比較

以下のコマンドを実行し、アプリの設定(ダークモードとか)を 最初に読み取ったあとの
sharedPreferencesRepositoryProvider の挙動を確認しましょう。

$ flutter run 

まず、①です。

├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter ( 5584): │ 💡 [ADD]: sharedPreferencesRepositoryProvider
I/flutter ( 5584): └───────────────────────────────────────────────────
....
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter ( 5584): │ 🐛 [DISPOSE]: sharedPreferencesRepositoryProvider
I/flutter ( 5584): └────────────────────────────────────────────────────────

次に ②です。

I/flutter ( 5584): │ 10:52:48.254 (+0:00:00.052326)
I/flutter ( 5584): ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter ( 5584): │ 💡 [ADD]: sharedPreferencesRepositoryProvider
I/flutter ( 5584): └───────────────────────────────────────────────────────────────────────────────

ちゃんと、riverpod_annotationが @Riverpod(keepAlive: true)のときは、 プロバイダーの状態がのこり続けていることがわかります。

⭐️ Providerの状態を把握できる → アプリケーションの状態管理が容易になり、デバッグやメンテナンスが簡単になる

手順

1. 以下のコードファイル利用する

// logger import
import 'package:flutter_riverpod/flutter_riverpod.dart';

class ProviderLogger implements ProviderObserver {
  const ProviderLogger();

  @override
  void didAddProvider(
    ProviderBase provider,
    Object? value,
    ProviderContainer container,
  ) {
    logger.i('[ADD]: ${provider.describe}');
  }

  @override
  void didDisposeProvider(
    ProviderBase provider,
    ProviderContainer container,
  ) {
    logger.d('[DISPOSE]: ${provider.describe}');
  }

  @override
  void didUpdateProvider(
    ProviderBase provider,
    Object? previousValue,
    Object? newValue,
    ProviderContainer container,
  ) {
    logger.i('[UPDATE]*: ${provider.describe}');
  }

  @override
  void providerDidFail(
    ProviderBase provider,
    Object error,
    StackTrace stackTrace,
    ProviderContainer container,
  ) {
    logger.e('[FAIL]: ${provider.describe}');
  }
}

extension _ProviderName on ProviderBase {
  String get describe => name ?? toString();
}

2. main.dart の observersに手順①を追加

 runApp(
    ProviderScope(
      overrides: [
   .....
      ],
      observers: [ProviderLogger()],
      child: const App(),
    ),
  );

まとめ

riverpod でDIを行うのは非常に便利ですよね!
そうなると、Providerの管理が大変になります。
積極的にProviderObserverを使用して、状態を監視していきましょう⭐️

Discussion