LoginSignup
10
10

More than 3 years have passed since last update.

Flutterアプリのフォアグラウンド/バックグラウンド時のイベントを整理したが、detachedだけでない件

Posted at

:book: Flutterの記事を整理し本にしました :book:

  • 本稿の記事を含む様々な記事を体系的に整理し本にまとめました
  • 今後はこちらを最新化するため、最新情報はこちらをご確認くださ
  • 10万文字を超える超大作になっています(笑)

はじめに

  • アプリの一時停止や復旧のアプリライフサイクルイベントを整理しました

まとめ

アプリライフサイクルとは

アプリは常にフォアグラウンドで画面に表示され、ユーザからの操作を受け付けているわけではありません。
別のアプリが割り込んだり、ユーザ操作でバックグラウンドに移されることがあります。
この一時停止や復旧に対応した処理を準備しておくことで、ユーザのUX改善につながる場合があります。

ソースコード

main.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance!.addObserver(this);
  }
  @override
  void dispose() {
    print("dispose");
    WidgetsBinding.instance!.removeObserver(this);
    super.dispose();
  }
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    print("stete = $state");
    switch (state) {
      case AppLifecycleState.inactive:
        print('非アクティブになったときの処理');
        break;
      case AppLifecycleState.paused:
        print('停止されたときの処理');
        break;
      case AppLifecycleState.resumed:
        print('再開されたときの処理');
        break;
      case AppLifecycleState.detached:
        print('破棄されたときの処理');
        break;
    }
  }
  int _counter = 0;
  _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

with WidgetsBindingObserverでミックスインをすることでアプリライフサイクルの管理が可能です。
didChangeAppLifecycleStateが状態の変更があった時に呼び出されるメソッドです。

状態は以下の4つが定義されています。

  • inactive
    • 非アクティブになった時
  • paused
    • バックグラウンドになった時
  • resumed
    • フォアグラウンドに再開された時
  • detached:
    • アプリが破棄された時

どの状態がどのタイミングで呼ばれるかは、機器やAndroid/iOSによって差があります。
詳細は、AppLifecycleStateの公式ドキュメントでご確認ください

動作確認

ホームボタン等をおして、バックグラウンドとフォアグラウンドを入れ替えると、コンソールにメッセージがでます。

pic11.png

バックグラウンドに移したときの表示

result.sh
I/flutter ( 5955): stete = AppLifecycleState.inactive
I/flutter ( 5955): 非アクティブになったときの処理
I/flutter ( 5955): stete = AppLifecycleState.paused
I/flutter ( 5955): 停止されたときの処理

フォアグラウンドに移したときの表示

result.sh
I/flutter ( 5955): stete = AppLifecycleState.resumed
I/flutter ( 5955): 再開されたときの処理

前述の通り、どの状態のイベントが呼ばれるかは機器やOSによって異なります。
detachedがアプリが終了した時に呼び出されるとされていますが、本チャプター執筆時に検証したエミュレータや実機では表示させることができませんでした。

ネットでもでないという記事をちらほら見かけますが、困ったな。。。

10
10
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
10
10