Flutter:在简历上更新小部件?
Posted
技术标签:
【中文标题】Flutter:在简历上更新小部件?【英文标题】:Flutter: Update Widgets On Resume? 【发布时间】:2018-09-26 22:26:00 【问题描述】:在 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<void> 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 来自docsIf 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 解决方案共有三种方法。
WidgetsBindingObserver
SystemChannels.lifecycle
flutter-android-lifecycle-plugin
WidgetsBindingObserver
和SystemChannels.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;
【讨论】:
以上是关于Flutter:在简历上更新小部件?的主要内容,如果未能解决你的问题,请参考以下文章
由于当前屏幕上的更新,防止 Flutter Provider 在前一屏幕中重建小部件