Table of Contents
別のアプリを起動したり端末をスリープさせたりすることでアプリがバックグラウンド状態になる際、何かしらの処理を行わせたいという場合があります。
Flutter では、状態を監視させたい Widget に WidgetsBindingObserver を設定すると、その中のメソッド didChangeAppLifecycleState でアプリの状態が変化した際に AppLifecycleState を受け取ることができます。
取得できるアプリの状態変化
取得できるアプリの状態変化には下記の5種類がありますが、端末のOSの種類(Android/iOS)によって受け取れる状態が若干異なるようです。以下のページを参考に、状態についてまとめてみます。
- How do I listen to iOS lifecycle events?
- How do I listen to Android activity lifecycle events?
- AppLifecycleState enum – dart:ui library – Dart API
detached
Flutterエンジン上で動作していながらもビューが無い状態。エンジンの初期起動時や Navigator.pop によってビューが破棄された際になるとのことです。
実際にテストしてみたところ、Android ではバックボタンでアプリからホーム画面に戻った際にこの状態になっていました。
inactive
ユーザーからの入力を受け取らない非アクティブ状態。
iOSでは、例えば、着信があった際やTouchIDの要求画面の表示、コントロールセンターを開いた時、UIViewControllerのトランジション時など。
Android では相当するイベントが無いとされていますが「参考3」には以下のような記述があります。
On Android, this corresponds to an app or the Flutter host view running in the foreground inactive state. Apps transition to this state when another activity is focused, such as a split-screen app, a phone call, a picture-in-picture app, a system dialog, or another window.
Android でもトランジションによって他のアクティビティがアクティブになったり、着信やピクチャ・イン・ピクチャの動画アプリのようなもの、システムダイアログなどによって inactive 状態になるようです。
実際に Android の実機でテストしてみると、バックグラウンドアプリ一覧画面を開いたとき(pixelでは画面下からの上方向スワイプ)に inactive の状態となっていました。iOSではホーム画面に戻る際やバックグラウンドアプリ一覧画面を開く時の他に、paused から resumed に移行する間にこの状態となっていました。
この状態のアプリは、いつでも pause 状態に移行する可能性があるとみなされます。実際のテストでも inactive となった後に pause となることが多かったです。
paused
アプリがユーザーに非表示であり入力も受け付けず、バックグラウンドで動作している状態。Android における onPause() に相当。
この状態の時、コールバック Window.onBeginFrame および Window.onDrawFrame は呼ばれないとのこと。
実機では完全にホーム画面に戻った時に paused となります。
resume
アプリがフォアグラウンドに移行した時。
アプリは可視状態となり、入力も受け取るようになる。Android における onPostResume() に相当。
suspending(Androidのみ)
アプリの一時停止状態。Android における onStop() に相当。iOSには相当するイベントは存在しない。
サンプル
「参考2」のサンプルコードを参考にした、アプリ状態を確認できる StatefulWidget のサンプルです。コンソールにログを残すように変更を加えています。
import 'dart:developer'; ...(mainなどは省略)... class Test extends StatefulWidget { @override _TestState createState() => _TestState(); } class _TestState extends State<Test> with WidgetsBindingObserver { AppLifecycleState _state; @override void initState() { super.initState(); // 状態監視を開始 WidgetsBinding.instance.addObserver(this); } @override void dispose() { // 状態監視のオブザーバーを破棄 WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { log('state: $state'); setState(() { // 状態変化を変数に格納 _state = state; }); } @override Widget build(BuildContext context) { if (_state == null) { return Text(''); } return Text('$_state'); } }
ログに状態の変化が記録されます。
以上、Flutter でアプリの状態変化を取得する方法についてでした。