💬
riverpodは ProviderObserverで状態を追跡しよう!
Flutter で開発をするとき、riverpodを使うプロジェクトはかなり多いのではないでしょうか。
本日は、Providerの生成や破棄、状態の変化の追跡について書いていこうと思います。
こんな人におすすめ
・riverpodをつかっている
・providerが生成、破壊されるタイミングを追跡したい
⭐️ loggerでproviderの状態を追跡できるようになります。
ProviderObserverとは
ProviderObserver は、Riverpodの機能の一つであり、Providerの状態変化を監視するために使用されます。これにより、プロバイダのライフサイクルイベント(読み込み、値の更新、削除など)を監視し、デバッグやロギングを行うことができます。
以下の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