onResume() 和 onPause() 用于 Flutter 上的小部件
onResume() and onPause() for widgets on Flutter
现在,一个小部件只有在第一次创建小部件时触发的 initeState() 和在小部件被销毁时触发的 dispose() 。有没有一种方法可以检测小部件何时返回前台?当一个小部件即将进入后台时,因为另一个小部件刚刚被置于前台?
它相当于 Android 触发的 onResume 和 onPause,以及 ios
触发的 viewWillAppear 和 viewWillDisappear
您想要执行此操作的最常见情况是您有动画 运行 并且您不想在后台消耗资源。在这种情况下,您应该使用 TickerProviderStateMixin
扩展 State
,并使用 State
作为 AnimationController
的 vsync
参数。当您的 State
可见时,Flutter 将只负责调用动画控制器的侦听器。
如果您希望 PageRoute
中的 State
在 PageRoute
被其他内容遮挡时被处理掉,您可以传递一个 maintainState
argument of false
to your PageRoute
constructor. If you do this, your State
will reset itself (and its children) when it's hidden and will have to re-construct itself in initState
using the properties passed in as constructor arguments to its widget
. You can use a model or controller class, or 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,
),
],
),
);
}
}
有一个抽象的class调用者WidgetsBindingObserver
https://docs.flutter.io/flutter/widgets/WidgetsBindingObserver-class.html
在
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
setState(() {
_notification = state;
});
}
有"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;
}
这是一个演示如何正确处理事情的完整示例,要对此进行测试,请按主页按钮并恢复应用程序,您将看到正在调用 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();
}
我来晚了一点,但为那些将来可能正在寻找它的人提供了完美的解决方案。 Navigator.push()
实际上是一个 Future。这意味着它有 then()
回调函数。所以 then()
将在您从第二个屏幕调用 Navigator.pop()
之后被调用。甚至您可以从第二个屏幕发送一些数据并访问第一个屏幕中的数据。
示例:
//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 的简历上调用。
我创建 visibility_aware_state 是因为它的行为类似于 Android 的 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);
}
}
Mamnarock您的回答正确但不完整,您分享的link不可用。
完整代码如下:
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();
}
}
正如评论中提到的 TeeTracker:
这是一个应用程序级别的生命周期,这意味着当整体恢复、不活动或暂停时,而不是单个小部件。
现在,一个小部件只有在第一次创建小部件时触发的 initeState() 和在小部件被销毁时触发的 dispose() 。有没有一种方法可以检测小部件何时返回前台?当一个小部件即将进入后台时,因为另一个小部件刚刚被置于前台? 它相当于 Android 触发的 onResume 和 onPause,以及 ios
触发的 viewWillAppear 和 viewWillDisappear您想要执行此操作的最常见情况是您有动画 运行 并且您不想在后台消耗资源。在这种情况下,您应该使用 TickerProviderStateMixin
扩展 State
,并使用 State
作为 AnimationController
的 vsync
参数。当您的 State
可见时,Flutter 将只负责调用动画控制器的侦听器。
如果您希望 PageRoute
中的 State
在 PageRoute
被其他内容遮挡时被处理掉,您可以传递一个 maintainState
argument of false
to your PageRoute
constructor. If you do this, your State
will reset itself (and its children) when it's hidden and will have to re-construct itself in initState
using the properties passed in as constructor arguments to its widget
. You can use a model or controller class, or 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,
),
],
),
);
}
}
有一个抽象的class调用者WidgetsBindingObserver
https://docs.flutter.io/flutter/widgets/WidgetsBindingObserver-class.html
在
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
setState(() {
_notification = state;
});
}
有"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;
}
这是一个演示如何正确处理事情的完整示例,要对此进行测试,请按主页按钮并恢复应用程序,您将看到正在调用 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();
}
我来晚了一点,但为那些将来可能正在寻找它的人提供了完美的解决方案。 Navigator.push()
实际上是一个 Future。这意味着它有 then()
回调函数。所以 then()
将在您从第二个屏幕调用 Navigator.pop()
之后被调用。甚至您可以从第二个屏幕发送一些数据并访问第一个屏幕中的数据。
示例:
//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 的简历上调用。
我创建 visibility_aware_state 是因为它的行为类似于 Android 的 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);
}
}
Mamnarock您的回答正确但不完整,您分享的link不可用。
完整代码如下:
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();
}
}
正如评论中提到的 TeeTracker:
这是一个应用程序级别的生命周期,这意味着当整体恢复、不活动或暂停时,而不是单个小部件。