【问题标题】:Flutter: Update Widgets On Resume?Flutter:在简历上更新小部件?
【发布时间】:2018-09-26 22:26:00
【问题描述】:

在 Flutter 中,有没有一种方法可以在用户离开应用程序并立即返回时更新小部件?我的应用是基于时间的,尽快更新时间会很有帮助。

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    您可以通过这样做来监听生命周期事件,例如:

    import 'package:flutter/material.dart';
    import 'package:flutter/foundation.dart';
    
    class LifecycleEventHandler extends WidgetsBindingObserver {
      final AsyncCallback resumeCallBack;
      final AsyncCallback suspendingCallBack;
    
      LifecycleEventHandler({
        this.resumeCallBack,
        this.suspendingCallBack,
      });
    
      @override
      Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
        switch (state) {
          case AppLifecycleState.resumed:
            if (resumeCallBack != null) {
              await resumeCallBack();
            }
            break;
          case AppLifecycleState.inactive:
          case AppLifecycleState.paused:
          case AppLifecycleState.detached:
            if (suspendingCallBack != null) {
              await suspendingCallBack();
            }
            break;
        }
      }
    }
    
    
    
    class AppWidgetState extends State<AppWidget> {
      void initState() {
        super.initState();
    
        WidgetsBinding.instance.addObserver(
          LifecycleEventHandler(resumeCallBack: () async => setState(() {
            // do something
          }))
        );
      }
      ...
    }
    

    【讨论】:

    • 我只是想知道,您可以将 WidgetsBindingObserver 添加到 StatelessWidget 吗?谢谢。
    • 当然可以,但是当这样的生命周期事件发生时你想做什么?
    • 你可以把上面的代码放在任何地方。它不必在小部件内。这只是一个例子。
    • FutureVoidCallback 在哪里定义?我在颤振包源中找不到它,谷歌也没有帮助?
    • @ChrisCrowe 你是对的。你需要自己声明。 typedef FutureVoidCallback = Future&lt;void&gt; Function();
    【解决方案2】:

    使用系统频道:

    import 'package:flutter/services.dart';
    
    SystemChannels.lifecycle.setMessageHandler((msg){
      debugPrint('SystemChannels> $msg');
      if(msg==AppLifecycleState.resumed.toString())setState((){});
    });
    

    `

    【讨论】:

    • 这对其他人来说可能很明显,但我花了一段时间才弄清楚我需要在 Flutter runApp 调用之后将其移动到某个位置。
    • 我们是否将这段代码放入 initState() 中? systemChannels 会像监听器一样监听生命周期的变化?
    • msg 变量的类型是什么?为什么不是 AppLifecycleState 类型?
    • @edhubbell 来自docs If you need the binding to be constructed before calling runApp, you can ensure a Widget binding has been constructed by calling the WidgetsFlutterBinding.ensureInitialized() function.
    【解决方案3】:

    简单的方法:

    import 'package:flutter/services.dart';
    
    handleAppLifecycleState() {
        AppLifecycleState _lastLifecyleState;
        SystemChannels.lifecycle.setMessageHandler((msg) {
    
         print('SystemChannels> $msg');
    
            switch (msg) {
              case "AppLifecycleState.paused":
                _lastLifecyleState = AppLifecycleState.paused;
                break;
              case "AppLifecycleState.inactive":
                _lastLifecyleState = AppLifecycleState.inactive;
                break;
              case "AppLifecycleState.resumed":
                _lastLifecyleState = AppLifecycleState.resumed;
                break;
              case "AppLifecycleState.suspending":
                _lastLifecyleState = AppLifecycleState.suspending;
                break;
              default:
            }
        });
      }
    

    只需在您的init() 中添加handleAppLifecycleState()

    class AppLifecycleReactor extends StatefulWidget {
          const AppLifecycleReactor({ Key key }) : super(key: key);
    
          @override
          _AppLifecycleReactorState createState() => _AppLifecycleReactorState();
        }
    
        class _AppLifecycleReactorState extends State<AppLifecycleReactor> with WidgetsBindingObserver {
          @override
          void initState() {
            super.initState();
            WidgetsBinding.instance.addObserver(this);
          }
    
          @override
          void dispose() {
            WidgetsBinding.instance.removeObserver(this);
            super.dispose();
          }
    
          AppLifecycleState _notification;
    
          @override
          void didChangeAppLifecycleState(AppLifecycleState state) {
            setState(() { _notification = state; });
          }
    
          @override
          Widget build(BuildContext context) {
            return Text('Last notification: $_notification');
          }
        }
    

    更多详情请参考documentation

    【讨论】:

      【解决方案4】:

      对于深度测试,我认为结果值得一读。如果您对应该使用哪种方法感到好奇,请阅读以下内容:(在 Android 上测试)

      LifeCycle 解决方案共有三种方法。

      1. WidgetsBindingObserver
      2. SystemChannels.lifecycle
      3. flutter-android-lifecycle-plugin

      WidgetsBindingObserverSystemChannels.lifecycle 的主要区别在于WidgetsBindingObserver 有更多的能力如果你有一堆小部件需要监听 LifeCycle。 SystemChannels 是更底层的,由WidgetsBindingObserver 使用。

      经过多次测试,如果你在runApp之后使用SystemChannels,并且home widget mixin与WidgetsBindingObserver,home widget会失败,因为SystemChannels.lifecycle.setMessageHandler覆盖了home的方法。

      因此,如果您想使用全局、单一的方法,请选择SystemChannels.lifecycle,其他人选择WidgetsBindingObserver

      那么第三种方法呢?这仅适用于 Android,如果您必须在 之前 runApp 绑定您的方法,这是唯一的方法。

      【讨论】:

      • 如果使用SystemChannels.lifecycle,则不会收到WidgetsBindingObserver 回调。
      • 加一详细说明
      【解决方案5】:
      import 'package:flutter/material.dart';
      
      abstract class LifecycleWatcherState<T extends StatefulWidget> extends State<T>
          with WidgetsBindingObserver {
        @override
        Widget build(BuildContext context) {
          return null;
        }
      
        @override
        void initState() {
          super.initState();
          WidgetsBinding.instance.addObserver(this);
        }
      
        @override
        void dispose() {
          WidgetsBinding.instance.removeObserver(this);
          super.dispose();
        }
      
        @override
        void didChangeAppLifecycleState(AppLifecycleState state) {
          switch (state) {
            case AppLifecycleState.resumed:
              onResumed();
              break;
            case AppLifecycleState.inactive:
              onPaused();
              break;
            case AppLifecycleState.paused:
              onInactive();
              break;
            case AppLifecycleState.detached:
              onDetached();
              break;
          }
        }
      
        void onResumed();
        void onPaused();
        void onInactive();
        void onDetached();
      }
      

      示例

      class ExampleStatefulWidget extends StatefulWidget {
        @override
        _ExampleStatefulWidgetState createState() => _ExampleStatefulWidgetState();
      }
      
      class _ExampleStatefulWidgetState
          extends LifecycleWatcherState<ExampleStatefulWidget> {
        @override
        Widget build(BuildContext context) {
          return Container();
        }
      
        @override
        void onDetached() {
      
        }
      
        @override
        void onInactive() {
      
        }
      
        @override
        void onPaused() {
      
        }
      
        @override
        void onResumed() {
      
        }
      }
      

      【讨论】:

        【解决方案6】:

        下面是一个如何观察包含活动 (Flutter for Android developers) 的生命周期状态的示例:

        import 'package:flutter/widgets.dart';
        
        class LifecycleWatcher extends StatefulWidget {
          @override
          _LifecycleWatcherState createState() => _LifecycleWatcherState();
        }
        
        class _LifecycleWatcherState extends State<LifecycleWatcher> with WidgetsBindingObserver {
          AppLifecycleState _lastLifecycleState;
        
          @override
          void initState() {
            super.initState();
            WidgetsBinding.instance.addObserver(this);
          }
        
          @override
          void dispose() {
            WidgetsBinding.instance.removeObserver(this);
            super.dispose();
          }
        
          @override
          void didChangeAppLifecycleState(AppLifecycleState state) {
            setState(() {
              _lastLifecycleState = state;
            });
          }
        
          @override
          Widget build(BuildContext context) {
            if (_lastLifecycleState == null)
              return Text('This widget has not observed any lifecycle changes.', textDirection: TextDirection.ltr);
        
            return Text('The most recent lifecycle state this widget observed was: $_lastLifecycleState.',
                textDirection: TextDirection.ltr);
          }
        }
        
        void main() {
          runApp(Center(child: LifecycleWatcher()));
        }
        

        【讨论】:

          【解决方案7】:

          使用“WidgetsBindingObserver”检测 onResume 事件的解决方案 或“SystemChannels.lifecycle”仅在应用程序完全进入后台时才有效,例如在锁定屏幕事件期间或切换到另一个应用程序期间。如果用户在应用程序的屏幕之间导航,它将不起作用。如果即使在同一应用的不同屏幕之间切换时也想检测 onResume 事件,请从此处使用 visibility_detector 库:https://pub.dev/packages/visibility_detector

            @override
          Widget build(BuildContext context) {
            return VisibilityDetector(
              key: Key('my-widget-key'),
              onVisibilityChanged: (visibilityInfo) {
                num visiblePercentage = visibilityInfo.visibleFraction * 100;
                debugPrint(
                    'Widget ${visibilityInfo.key} is ${visiblePercentage}% visible');
                if(visiblePercentage == 100){
                          debugPrint("Resumed !");
                        }
              },
              child: someOtherWidget,
            );
          }
          

          【讨论】:

            【解决方案8】:

            如果你想执行 onResume 方法但只在一个页面中,你可以在你的页面中添加这个:

            var lifecycleEventHandler;
            
            @override
              void initState() {
                super.initState();
            
                ///To listen onResume method
                lifecycleEventHandler = LifecycleEventHandler(
                    resumeCallBack: () async {
                      //do something
                    }
                );
                WidgetsBinding.instance.addObserver(lifecycleEventHandler);
              }
            
            @override
              void dispose() {
                if(lifecycleEventHandler != null)
                  WidgetsBinding.instance.removeObserver(lifecycleEventHandler);
            
                super.dispose();
              }
            

            并将 LifecycleEventHandler 类作为这篇文章的第一个答案:

            import 'package:flutter/material.dart';
            import 'package:flutter/foundation.dart';
            
            class LifecycleEventHandler extends WidgetsBindingObserver {
              final AsyncCallback resumeCallBack;
              final AsyncCallback suspendingCallBack;
            
              LifecycleEventHandler({
                this.resumeCallBack,
                this.suspendingCallBack,
              });
            
              @override
              Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
                switch (state) {
                  case AppLifecycleState.resumed:
                    if (resumeCallBack != null) {
                      await resumeCallBack();
                    }
                    break;
                  case AppLifecycleState.inactive:
                  case AppLifecycleState.paused:
                  case AppLifecycleState.detached:
                    if (suspendingCallBack != null) {
                      await suspendingCallBack();
                    }
                    break;
                }
              }
            }
            

            【讨论】:

              猜你喜欢
              • 2020-04-08
              • 2021-08-06
              • 2018-11-01
              • 2020-08-18
              • 1970-01-01
              • 2020-06-23
              • 2020-09-17
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多