LoginSignup
16
11

More than 3 years have passed since last update.

FlutterアプリでonResume的なタイミングの処理をする/複数ウィジェットで監視編

Posted at

Flutterアプリで、AndroidでいうonResumeのタイミング(アプリがホームボタンなどでバックグラウンドに行ってまた前面に戻ったとき)で処理をしたいと思い、以下の記事を書きました。

FlutterアプリでonResume的なタイミングの処理をする
https://qiita.com/kasa_le/items/1fdbe07112ab4aed250a

しかし、複数のウィジェットで同時多発的に監視したいときに、この方法では問題がありました。
関数名を見て貰えれば分かりますが、set***なので、最後にセットしたコールバックしか呼ばれません。

ということで、対処法を調べたのでそのまとめです。

環境など

ツールなど バージョンなど
MacBook Air Early2015 macOS Mojave 10.14.6
Android Studio 3.6.1
Java 1.8.0_131
Flutter 1.12.13+hotfix.9
Dart 2.7.2
Xcode 11.3.1

解決策

WidgetsBindingObserverを使います。

1.StatefulWidgetで使う

基本的に、WidgetsBindingObserverStatefulWidgetでなければ使えません。

class SomeWidget extends StatefulWidget {
 @override
  State<StatefulWidget> createState() => _SomeState();
}

class _SomeState extends State<SomeWidget> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      // onResume処理
    }
  }

  @override
  Widget build(BuildContext context) {
     return ...
  }
}

だいたいこんな感じで使えます。

2.LifecycleManagerクラスを作る

よくあるコールバック方式で、こんな方法も出来ます。

LifecycleManager.dart
/// ライフサイクルコールバックインターフェース
class LifecycleCallback {
  void onResumed() {}

  void onPaused() {}

  void onInactive() {}

  void onDetached() {}
}

/// ライフサイクルを受け取れるStatefulWidget
class LifecycleManager extends StatefulWidget {
  final Widget child;
  final LifecycleCallback callback;

  LifecycleManager({Key key, this.child, this.callback}) : super(key: key);

  _LifeCycleManagerState createState() => _LifeCycleManagerState();
}

class _LifeCycleManagerState extends State<LifecycleManager>
    with WidgetsBindingObserver {
  @override
  void initState() {
    WidgetsBinding.instance.addObserver(this);
    super.initState();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    print('state = $state');
    switch (state) {
      case AppLifecycleState.resumed:
        widget.callback?.onResumed();
        break;
      case AppLifecycleState.inactive:
        widget.callback?.onInactive();
        break;
      case AppLifecycleState.paused:
        widget.callback?.onPaused();
        break;
      case AppLifecycleState.detached:
        widget.callback?.onDetached();
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: widget.child,
    );
  }
}

で、StatelessWidget#buildなどでこう返します。

   return LifecycleManager(
      callback: _onLifecycleCallback,
      child: MyWidget(),
   );

基本的にStatelessWidgetで作っていたりすると、onResume処理が必要なウィジェットだけStatetulWidgetに変えていくのも結構面倒だったりします。そこで、このLifecycleManagerで「括ってしまえば」ちょっとは楽かと思います。

参考サイト

https://stackoverflow.com/questions/49869873/flutter-update-widgets-on-resume
https://medium.com/flutter-community/build-a-lifecycle-manager-to-manage-your-services-b9c928d3aed7

16
11
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
16
11