Chapter 32無料公開

アプリのライフサイクルを監視するProvider

村松龍之介
村松龍之介
2023.02.06に更新

起動しているアプリがバックグラウンド実行になった時、またはアクティブ状態に再開した等を検知して何か処理を実行したいことがあります。

そういったアプリのライフサイクルは、Flutterでは enum AppLifecycleState として定義されています。

enum AppLifecycleState {
  resumed,
  inactive,
  paused,
  detached,
}

https://docs-flutter-io.firebaseapp.com/flutter/dart-ui/AppLifecycleState-class.html

これらのライフサイクル変更をRiverpodのProviderを使用して監視できるようにしましょう👍

全体の実装コードは以下のサンプルリポジトリの該当ファイルで確認できます↓
https://github.com/altive/flutter_app_template/blob/main/packages/flutter_app/lib/util/providers/app_lifecycle_state_provider.dart

それでは、以下で1つずつ説明していきます。

Observerクラスを定義

まずは、 WidgetsBindingObserver を継承したクラスを作成します。

class _AppLifecycleObserver extends WidgetsBindingObserver {
  _AppLifecycleObserver(this._didChangeState);

  final ValueChanged<AppLifecycleState> _didChangeState;

  
  void didChangeAppLifecycleState(AppLifecycleState state) {
    _didChangeState(state);
    super.didChangeAppLifecycleState(state);
  }
}

ここでは _AppLifecycleObserver という名前にしました。

外部から処理を追加できるように(コールバックを渡せるように)、 _didChangeState というプロパティを定義してコンストラクタで処理を渡せるようにしておきます。

WidgetsBindingObserverdidChangeAppLifecycleState というメソッドを持つのでこれをオーバーライドしましょう。
このメソッドの引数で AppLifecycleState 、すなわちアプリのライフサイクル状態を取得できます。

ここで _didChangeState メソッドに AppLifecycleState state を渡します。
super を使って継承元の didChangeAppLifecycleState メソッドも実行しておきましょう。

Providerを作成

Riverpodのプロバイダを通じて _AppLifecycleObserver を使用するためにProviderを定義します。
まず _AppLifecycleObserver をインスタンス化して observer という名前で受け取りましょう。

この時、 _didChangeState で実行される処理を渡しています。
value (AppLifecycleState) を受け取ったら ref.state = value で自信の値を変更しています。

WidgetsBinding.instance..addObserverobserver を登録。

ref.onDispose で、Providerが破棄されたときに observer を解除しています。

最後に、初期値として AppLifecycleState.resumed を返しています。

final appLifecycleProvider = Provider<AppLifecycleState>((ref) {
  final observer = _AppLifecycleObserver((value) => ref.state = value);

  final binding = WidgetsBinding.instance..addObserver(observer);
  ref.onDispose(() => binding.removeObserver(observer));

  return AppLifecycleState.resumed;
});

Widgetからの使用例

ref.listen を使用してアプリのライフサイクルを検知する例です。
ref が使用できる箇所であれば同じようにどこでも監視可能ですし、リビルドさせたい場合は ref.watch でも使用できます。

行いたい処理の責務にあった箇所でプロバイダを購読してライフサイクルを取得しましょう。

class App extends ConsumerWidget {
  const App({
    super.key,
  });

  
  Widget build(BuildContext context, WidgetRef ref) {
    // appLifecycleProviderの状態変更を監視
    ref.listen<AppLifecycleState>(
        appLifecycleProvider,
        // `next` に変更された `AppLifecycleState` が入ってきます。
        // 任意の処理を行いましょう。
        (previous, next) => debugPrint('Previous: $previous, Next: $next'),
      );
    return const SplashPage();
  }
}

参考元

Riverpod作者であるRemiさんのこちらのツイート内コードを参考にさせていただきました。
https://twitter.com/remi_rousselet/status/1486675682491092997

https://twitter.com/riscait/status/1487008441386569732