🐷

Flutter/riverpod/FlutterHookでアプリのライフサイクルイベントを検知

2022/06/08に公開

下記を参考にしていますが、今回のはriverpod v0.14.0 + FlutterHookでの利用例のためちょっと変えています。
riverpod v1.0系使えばもっとうまくできるはず。その辺はまた別で書こうと思います。
riverpod v1系も追記。ほとんど👇の素晴らしい参考例と同じ。

https://zenn.dev/riscait/books/flutter-riverpod-practical-introduction/viewer/v2-app-lifecycle

ライフサイクルイベントを検知関連

  • ライフサイクルイベントを監視するAppLifecycleObserverクラスを返すProvider

riverpod v1系

final appLifecycleProvider = Provider<AppLifecycleState>((ref) {
  final observer = _AppLifecycleObserver((state) => ref.state = state);
  final binding = WidgetsBinding.instance?..addObserver(observer);
  ref.onDispose(() => binding?.removeObserver(observer));
  return AppLifecycleState.resumed;
});

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

  ValueChanged<AppLifecycleState> _didChangeState;

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

HookWidget側での利用

class HogePage extends HookConsumerWidget {
  const HogePage({
    Key? key,
  }) : super(key: key);
  
  
  Widget build(BuildContext context, WidgetRef ref) {
    ref.listen<AppLifecycleState>(appLifecycleProvider, (previous, next) {
      switch (appLifecycle) {
        case AppLifecycleState.resumed:
          break;
        case AppLifecycleState.inactive:
          break;
        case AppLifecycleState.paused:
          break;
        case AppLifecycleState.detached:
          break;
      }
    });
  }

riverpod v0.14.0

import 'package:flutter/widgets.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

final appLifecycleProvider = Provider<AppLifecycleObserver>((ref) {
  final observer = AppLifecycleObserver();
  final binding = WidgetsBinding.instance?..addObserver(observer);
  ref.onDispose(() => binding?.removeObserver(observer));
  return observer;
});

class AppLifecycleObserver extends WidgetsBindingObserver {
  AppLifecycleObserver();

  ValueChanged<AppLifecycleState>? didChangeState;

  
  void didChangeAppLifecycleState(AppLifecycleState state) {
    didChangeState?.call(state);
    super.didChangeAppLifecycleState(state);
  }
}

HookWidget側での利用

class HogePage extends HookWidget {
  const HogePage({
    Key? key,
  }) : super(key: key);
  
  
  Widget build(BuildContext context) {
    final appLifecycleObserver = useProvider(appLifecycleProvider);
    appLifecycleObserver.didChangeState = (appLifecycle) {
      switch (appLifecycle) {
        case AppLifecycleState.resumed:
          break;
        case AppLifecycleState.inactive:
          break;
        case AppLifecycleState.paused:
          break;
        case AppLifecycleState.detached:
          break;
      }
    };
    
    useEffect(() {
      // dispose時にdidChangeStateのコールバックをnullにセットして監視を解除
      return (() => appLifecycleObserver.didChangeState = null);
    }, const []);
  }

※これだと、全面表示中のWidgetでしか、ライフサイクルをフックできません...

Discussion