1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

riverpodのライフサイクル

Posted at

Flutterでアプリ開発する場合、状態管理をRiverpoodで実装するケースは多いと思います。本記事は、Riverpodの状態のライフサイクルについて纏めました。

Riverpod とは?

Riverpod は、Flutter における状態管理の課題を解決するために設計されたフレームワークです。Provider の欠点を克服し、より型安全で保守性の高いコードを書くことができます。

Provider のライフサイクル

Riverpod における Provider のライフサイクルを理解することは、効率的な状態管理を行う上で非常に重要です。以下に、Provider のライフサイクルの主要なフェーズを示します。

1. 作成 (Creation)

Provider は、最初に定義されたとき「作成」されますが、実際にインスタンス化されるのは最初に使用されるときです。

final counterProvider = StateProvider<int>((ref) {
  print('CounterProvider が初期化されました');
  return 0;
});

2. 初期化 (Initialization)

Provider が最初に読み取られたとき、つまり .watch().read() メソッドが呼び出されたときに初期化されます。この時点で Provider の値が計算され、メモリに保持されます。

3. 依存関係の追跡 (Dependency Tracking)

Riverpod の強力な機能の一つは、Provider 間の依存関係を自動的に追跡することです。あるプロバイダーが別のプロバイダーを監視(watch)すると、依存関係が確立されます。

final doubledCounterProvider = Provider<int>((ref) {
  // counterProvider への依存関係を確立
  final count = ref.watch(counterProvider);
  return count * 2;
});

4. 更新 (Update)

Provider の値が変更されると、その Provider を監視しているすべての依存関係に通知が送られ、再評価されます。

5. 破棄 (Disposal)

Provider が不要になると、そのリソースを解放するために破棄されます。これには主に二つのケースがあります:

  1. .autoDispose モディファイアを使用していて、Provider に監視者がいなくなった場合
  2. ref.onDispose() コールバックが実行される場合(例:ProviderScope が破棄されるとき)
final timerProvider = StreamProvider.autoDispose<int>((ref) {
  final controller = StreamController<int>();
  
  // タイマーのセットアップ
  final timer = Timer.periodic(Duration(seconds: 1), (timer) {
    controller.add(timer.tick);
  });
  
  // 破棄時にリソースをクリーンアップ
  ref.onDispose(() {
    print('timerProvider が破棄されました');
    timer.cancel();
    controller.close();
  });
  
  return controller.stream;
});

autoDispose モディファイアの影響

autoDispose モディファイアを使用すると、Provider のライフサイクルが変わります。このモディファイアを使用した Provider は、監視者がいなくなると自動的に破棄されます。

final weatherProvider = FutureProvider.autoDispose<Weather>((ref) {
  print('WeatherProvider が作成されました');
  
  // キャッシュしたい場合は、Provider の破棄を防ぐことができます
  ref.keepAlive();
  
  ref.onDispose(() {
    print('WeatherProvider が破棄されました');
  });
  
  return fetchWeather();
});

依存関係のライフサイクルと再評価

Riverpod では、Provider の依存関係が変更されると、その Provider も再評価されます。

ProviderScope と Provider のライフサイクル

Riverpod の各 Provider は、ProviderScope ウィジェット内で管理されます。ProviderScope が破棄されると、その配下のすべての Provider も破棄されます。

void main() {
  runApp(
    // アプリケーション全体のProviderScope
    ProviderScope(
      child: MyApp(),
    ),
  );
}

// ネストされたProviderScopeの例
Widget build(BuildContext context) {
  return ProviderScope(
    // このスコープ内のProviderはこのウィジェットが破棄されると
    // すべて破棄されます
    overrides: [
      // 特定のProviderをオーバーライドすることも可能
      counterProvider.overrideWithValue(StateController(10)),
    ],
    child: SomeWidget(),
  );
}

ref.listenのライフサイクル

ref.listen メソッドを使用すると、Provider の状態変化を監視し、その変化に反応することができます。

ref.listen<int>(counterProvider, (previous, next) {
  if (previous != null && next > previous) {
    print('カウンターが増加しました: $previous -> $next');
  }
});

このリスナーは、ref オブジェクトが属する Provider または Widget が破棄されるまで有効です。

まとめ

Riverpod の Provider は以下のライフサイクルを持ちます:

  1. 作成 - Provider が定義されるとき
  2. 初期化 - Provider が最初に使用されるとき
  3. 依存関係の追跡 - Provider が他の Provider を監視するとき
  4. 更新 - Provider の値が変更されるとき
  5. 破棄 - Provider が不要になり、リソースが解放されるとき

Riverpod はこのライフサイクルを通じて、効率的なメモリ管理と状態管理を実現します。autoDispose モディファイアやオーバーライドの仕組みを活用することで、さらに柔軟な状態管理が可能になります。

適切にライフサイクルを理解し、活用することで、パフォーマンスが高く、メンテナンスしやすいFlutterアプリケーションを構築することができます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?