现在,小部件只有initeState()和dispose(),initeState()在小部件第一次创建时被触发,dispose()在小部件被销毁时被触发。有没有一种方法可以检测小部件何时返回到前台?当一个小部件即将进入后台,因为另一个小部件刚刚被前景化?它相当于Android的onResume和onPause被触发,iOS的viewWillAppear和viewWillDisappear被触发
unhi4e5o1#
有一个抽象类调用者WidgetsBindingObserverhttps://docs.flutter.io/flutter/widgets/WidgetsBindingObserver-class.html在
@override void didChangeAppLifecycleState(AppLifecycleState state) { setState(() { _notification = state; }); }
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
setState(() {
_notification = state;
});
}
存在“状态”,可以管理为
switch(state) { case AppLifecycleState.resumed: // Handle this case break; case AppLifecycleState.inactive: // Handle this case break; case AppLifecycleState.paused: // Handle this case break; case AppLifecycleState.suspending: // Handle this case break;}
switch(state) {
case AppLifecycleState.resumed:
// Handle this case
break;
case AppLifecycleState.inactive:
case AppLifecycleState.paused:
case AppLifecycleState.suspending:
pinkon5k2#
这是一个完整的例子,演示了如何正确地处理事情,要测试这一点,按下主页按钮,并恢复应用程序,你会看到didChangeAppLifecycleState被调用。
didChangeAppLifecycleState
class HomePage extends StatefulWidget { @override _HomePageState createState() => _HomePageState();}class _HomePageState extends State<HomePage> with WidgetsBindingObserver { @override void initState() { super.initState(); // Add the observer. WidgetsBinding.instance!.addObserver(this); } @override void dispose() { // Remove the observer WidgetsBinding.instance!.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); // These are the callbacks switch (state) { case AppLifecycleState.resumed: // widget is resumed break; case AppLifecycleState.inactive: // widget is inactive break; case AppLifecycleState.paused: // widget is paused break; case AppLifecycleState.detached: // widget is detached break; } } @override Widget build(BuildContext context) => Scaffold();}
class HomePage extends StatefulWidget {
_HomePageState createState() => _HomePageState();
class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
void initState() {
super.initState();
// Add the observer.
WidgetsBinding.instance!.addObserver(this);
void dispose() {
// Remove the observer
WidgetsBinding.instance!.removeObserver(this);
super.dispose();
super.didChangeAppLifecycleState(state);
// These are the callbacks
switch (state) {
// widget is resumed
// widget is inactive
// widget is paused
case AppLifecycleState.detached:
// widget is detached
Widget build(BuildContext context) => Scaffold();
ryhaxcpt3#
最常见的情况是,如果您有一个动画正在运行,并且您不想在后台消耗资源,则需要执行此操作。在这种情况下,您应该使用TickerProviderStateMixin扩展State,并使用State作为AnimationController的vsync参数。Flutter只会在State可见时调用动画控制器的侦听器。如果希望在PageRoute被其他内容遮挡时释放PageRoute中的State,可以将false的maintainState参数传递给PageRoute构造函数。如果这样做,State将在隐藏时重置自身(及其子对象),并且必须使用作为widget的构造函数参数传入的属性在initState中重新构造自身。如果不想完全重置,可以使用模型或控制器类或PageStorage来保存用户的进度信息。下面是一个示例应用程序,演示了这些概念。
TickerProviderStateMixin
State
AnimationController
vsync
PageRoute
false
maintainState
widget
initState
PageStorage
import 'package:flutter/material.dart';void main() { runApp(new MaterialApp( onGenerateRoute: (RouteSettings settings) { if (settings.name == '/') { return new MaterialPageRoute<Null>( settings: settings, builder: (_) => new MyApp(), maintainState: false, ); } return null; } ));}class MyApp extends StatefulWidget { MyAppState createState() => new MyAppState();}class MyAppState extends State<MyApp> with TickerProviderStateMixin { AnimationController _controller; @override void initState() { print("initState was called"); _controller = new AnimationController(vsync: this) ..repeat(min: 0.0, max: 1.0, period: const Duration(seconds: 1)) ..addListener(() { print('animation value ${_controller.value}'); }); super.initState(); } @override void dispose() { print("dispose was called"); _controller.dispose(); super.dispose(); } int _counter = 0; @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text('home screen') ), body: new Center( child: new RaisedButton( onPressed: () { setState(() { _counter++; }); }, child: new Text('Button pressed $_counter times'), ), ), floatingActionButton: new FloatingActionButton( child: new Icon(Icons.remove_red_eye), onPressed: () { Navigator.push(context, new MaterialPageRoute( builder: (BuildContext context) { return new MySecondPage(counter: _counter); }, )); }, ), ); }}class MySecondPage extends StatelessWidget { MySecondPage({ this.counter }); final int counter; Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text('Certificate of achievement'), ), body: new Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ new Icon(Icons.developer_mode, size: 200.0), new Text( 'Congrats, you clicked $counter times.', style: Theme.of(context).textTheme.title, textAlign: TextAlign.center, ), new Text( 'All your progress has now been lost.', style: Theme.of(context).textTheme.subhead, textAlign: TextAlign.center, ), ], ), ); }}
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
onGenerateRoute: (RouteSettings settings) {
if (settings.name == '/') {
return new MaterialPageRoute<Null>(
settings: settings,
builder: (_) => new MyApp(),
maintainState: false,
);
return null;
));
class MyApp extends StatefulWidget {
MyAppState createState() => new MyAppState();
class MyAppState extends State<MyApp> with TickerProviderStateMixin {
AnimationController _controller;
print("initState was called");
_controller = new AnimationController(vsync: this)
..repeat(min: 0.0, max: 1.0, period: const Duration(seconds: 1))
..addListener(() {
print('animation value ${_controller.value}');
print("dispose was called");
_controller.dispose();
int _counter = 0;
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('home screen')
),
body: new Center(
child: new RaisedButton(
onPressed: () {
_counter++;
},
child: new Text('Button pressed $_counter times'),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.remove_red_eye),
Navigator.push(context, new MaterialPageRoute(
builder: (BuildContext context) {
return new MySecondPage(counter: _counter);
class MySecondPage extends StatelessWidget {
MySecondPage({ this.counter });
final int counter;
title: new Text('Certificate of achievement'),
body: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
new Icon(Icons.developer_mode, size: 200.0),
new Text(
'Congrats, you clicked $counter times.',
style: Theme.of(context).textTheme.title,
textAlign: TextAlign.center,
'All your progress has now been lost.',
style: Theme.of(context).textTheme.subhead,
],
relj7zay4#
我有点晚,但来了完美的解决方案,为那些谁可能正在寻找它在未来。Navigator.push()实际上是未来。表示它有then()回调函数。所以then()将在您从第二个屏幕调用Navigator.pop()之后被调用。甚至你可以从第二个屏幕发送一些数据,并在第一个屏幕中访问数据。举例说明:
Navigator.push()
then()
Navigator.pop()
//from Screen ANavigator.of(context).push(MaterialPageRoute(builder:(context)=>B())).then((value)=>{ refresh() });//in Screen B with dataNavigator.pop(context,[1]);//or without dataNavigator.pop(context);
//from Screen A
Navigator.of(context).push(MaterialPageRoute(builder:(context)=>B()))
.then((value)=>{ refresh() });
//in Screen B with data
Navigator.pop(context,[1]);
//or without data
Navigator.pop(context);
所以refresh()将在屏幕A的恢复上被调用。
refresh()
3wabscal5#
我创建visibility_aware_state是为了让它的行为类似于Android的Activity.onResume()。它还考虑了弹出和推送导航。
Activity.onResume()
class Example extends StatefulWidget { @override _ExampleState createState() => _ExampleState();}class _ExampleState extends VisibilityAwareState<Example> { @override Widget build(BuildContext context) { // return your widget } @override void onVisibilityChanged(WidgetVisibility visibility) { switch(visibility) { case WidgetVisibility.VISIBLE: // Like Android's Activity.onResume() break; case WidgetVisibility.INVISIBLE: // Like Android's Activity.onPause() break; case WidgetVisibility.GONE: // Like Android's Activity.onDestroy() break; } super.onVisibilityChanged(visibility); }}
class Example extends StatefulWidget {
_ExampleState createState() => _ExampleState();
class _ExampleState extends VisibilityAwareState<Example> {
// return your widget
void onVisibilityChanged(WidgetVisibility visibility) {
switch(visibility) {
case WidgetVisibility.VISIBLE:
// Like Android's Activity.onResume()
case WidgetVisibility.INVISIBLE:
// Like Android's Activity.onPause()
case WidgetVisibility.GONE:
// Like Android's Activity.onDestroy()
super.onVisibilityChanged(visibility);
mbskvtky6#
Mamnarock您的答案正确但不完整,您共享的链接不可用。下面是完整的代码:
import 'package:flutter/material.dart';class YourClass extends StatefulWidget { @override _YourClassState createState() => _YourClassState();}class _YourClassState extends State<YourClass> 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) { switch (state) { case AppLifecycleState.resumed: // Handle this case break; case AppLifecycleState.inactive: // Handle this case break; case AppLifecycleState.paused: // Handle this case break; case AppLifecycleState.detached: // Handle this case break; } } @override Widget build(BuildContext context) { return Container(); }}
class YourClass extends StatefulWidget {
_YourClassState createState() => _YourClassState();
class _YourClassState extends State<YourClass>
with WidgetsBindingObserver {
WidgetsBinding.instance.addObserver(this);
WidgetsBinding.instance.removeObserver(this);
return Container();
正如TeeTracker在评论中提到的:这是一个应用程序级别的生命周期,这意味着当整体恢复或不活动或暂停时,而不是单个小部件。
4zcjmb1e7#
如果您安装了Flutter Hooks(https://pub.dev/packages/flutter_hooks):
@overrideWidget build(BuildContext context) { useOnAppLifecycleStateChange((previous, current) => null);}
useOnAppLifecycleStateChange((previous, current) => null);
7条答案
按热度按时间unhi4e5o1#
有一个抽象类调用者WidgetsBindingObserver
https://docs.flutter.io/flutter/widgets/WidgetsBindingObserver-class.html
在
存在“状态”,可以管理为
pinkon5k2#
这是一个完整的例子,演示了如何正确地处理事情,要测试这一点,按下主页按钮,并恢复应用程序,你会看到
didChangeAppLifecycleState
被调用。ryhaxcpt3#
最常见的情况是,如果您有一个动画正在运行,并且您不想在后台消耗资源,则需要执行此操作。在这种情况下,您应该使用
TickerProviderStateMixin
扩展State
,并使用State
作为AnimationController
的vsync
参数。Flutter只会在State
可见时调用动画控制器的侦听器。如果希望在
PageRoute
被其他内容遮挡时释放PageRoute
中的State
,可以将false
的maintainState
参数传递给PageRoute
构造函数。如果这样做,State
将在隐藏时重置自身(及其子对象),并且必须使用作为widget
的构造函数参数传入的属性在initState
中重新构造自身。如果不想完全重置,可以使用模型或控制器类或PageStorage
来保存用户的进度信息。下面是一个示例应用程序,演示了这些概念。
relj7zay4#
我有点晚,但来了完美的解决方案,为那些谁可能正在寻找它在未来。
Navigator.push()
实际上是未来。表示它有then()
回调函数。所以then()
将在您从第二个屏幕调用Navigator.pop()
之后被调用。甚至你可以从第二个屏幕发送一些数据,并在第一个屏幕中访问数据。举例说明:
所以
refresh()
将在屏幕A的恢复上被调用。3wabscal5#
我创建visibility_aware_state是为了让它的行为类似于Android的
Activity.onResume()
。它还考虑了弹出和推送导航。mbskvtky6#
Mamnarock您的答案正确但不完整,您共享的链接不可用。
下面是完整的代码:
正如TeeTracker在评论中提到的:
这是一个应用程序级别的生命周期,这意味着当整体恢复或不活动或暂停时,而不是单个小部件。
4zcjmb1e7#
如果您安装了Flutter Hooks(https://pub.dev/packages/flutter_hooks):