Does flutter have a method like Activity.resume()
which can tell developer the user has gone back to the activity.
When I pick the data from internet in Page-B and go back to Page-A, how can I let Page-A know that the data is prepared.
Does flutter have a method like Activity.resume()
which can tell developer the user has gone back to the activity.
When I pick the data from internet in Page-B and go back to Page-A, how can I let Page-A know that the data is prepared.
createState()
:
当Framework被指示构建StatefulWidget时,它立即调用createState()
mounted
为真:
当createState
创建您的状态类时,将 abuildContext
分配给该状态。buildContext
是,过于简化,在部件树中放置这个部件的位置。这是一个更长的解释。所有小部件都有一个bool this.mounted
属性。buildContext
分配时变为真。setState
卸载小部件时调用是错误的。
initState()
:
这是创建小部件时调用的第一个方法(当然是在类构造函数之后。)initState
调用一次且仅调用一次。它必须调用super.initState()
.
didChangeDependencies()
:initState
在第一次构建小部件
后立即调用此方法。
build()
:
这个方法经常被调用。它是必需的,它必须返回一个 Widget。
didUpdateWidget(Widget oldWidget)
:
如果父部件发生变化并且必须重建这个部件(因为它需要给它不同的数据),但是它正在用相同的 重建runtimeType
,那么这个方法被调用。这是因为 Flutter 正在重用状态,这是长期存在的。在这种情况下,您可能需要再次初始化一些数据,就像在initState
.
setState()
:
这个方法经常被框架本身和开发者调用。它用于通知框架数据已更改
deactivate()
:
当从树中移除 State 时调用 Deactivate,但它可能会在当前帧更改完成之前重新插入。这种方法的存在基本上是因为 State 对象可以从树中的一个点移动到另一个点。
dispose()
:
dispose()
当状态对象被移除时调用,这是永久的。此方法是您应该取消订阅和取消所有动画、流等的地方。
mounted
为假:setState
状态对象永远不能重新挂载,如果被调用
会抛出错误。
这个函数不属于生命周期,因为此时widget属性的State为空,如果要在构造函数中访问widget属性是行不通的。但构造函数必须是第一次调用。
创建状态
当 Flutter 被指示构建一个StatefulWidget
.createState()
初始状态
当此对象插入树中时调用。
在调用时插入渲染树时,该函数在生命周期中只调用一次。这里可以做一些初始化,比如初始化State变量。
设置状态
该setState()
方法经常被 Flutter 框架本身和开发者调用。
didChangeDependencies
当此 [State] 对象的依赖项发生更改时调用。
didUpdateWidget
每当小部件配置更改时调用。
停用
当从树中删除此对象时调用。在 dispose 之前,我们将调用这个函数。
处置
当此对象从树中永久删除时调用。
didChangeAppLifecycleState
当系统将应用程序置于后台或将应用程序返回到前台时调用。
这里有一个很好的详细文档:https ://www.bookstack.cn/read/flutterbyexample/aebe8dda4df3319f.md
import 'package:flutter/material.dart';
class ScreenLifecyle extends StatefulWidget {
ScreenLifecyleState state;
//createState(): When the Framework is instructed to build a StatefulWidget, it immediately calls createState()
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return ScreenLifecyleState();
}
}
class ScreenLifecyleState extends State<ScreenLifecyle> {
/*
mounted is true: When createState creates your state class, a buildContext is assigned to that state.
BuildContext is, overly simplified, the place in the widget tree in which this widget is placed.
Here's a longer explanation. All widgets have a bool this.mounted property.
It is turned true when the buildContext is assigned. It is an error to call setState when a widget is unmounted.
mounted is false: The state object can never remount, and an error is thrown is setState is called.
*/
/*
This is the first method called when the widget is created (after the class constructor, of course.)
initState is called once and only once. It must called super.initState().
*/
@override
void initState() {
// TODO: implement initState
super.initState();
print("initState");
}
/*
This method is called immediately after initState on the first time the widget is built.
*/
@override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
print("didChangeDependencies");
}
/*
build(): This method is called often. It is required, and it must return a Widget.
*/
@override
Widget build(BuildContext context) {
print("build");
// TODO: implement build
return Container();
}
/*
If the parent widget changes and has to rebuild this widget (because it needs to give it different data),
but it's being rebuilt with the same runtimeType, then this method is called.
This is because Flutter is re-using the state, which is long lived.
In this case, you may want to initialize some data again, as you would in initState.
*/
@override
void didUpdateWidget(ScreenLifecyle oldWidget) {
print("didUpdateWidget");
// TODO: implement didUpdateWidget
super.didUpdateWidget(oldWidget);
}
@override
void setState(fn) {
print("setState");
// TODO: implement setState
super.setState(fn);
}
/*
Deactivate is called when State is removed from the tree,
but it might be reinserted before the current frame change is finished.
This method exists basically because State objects can be moved from one point in a tree to another.
*/
@override
void deactivate() {
// TODO: implement deactivate
print("deactivate");
super.deactivate();
}
/*
Dispose is called when the State object is removed, which is permanent.
This method is where you should unsubscribe and cancel all animations, streams, etc.
*/
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
switch (state) {
case AppLifecycleState.inactive:
print('appLifeCycleState inactive');
break;
case AppLifecycleState.resumed:
print('appLifeCycleState resumed');
break;
case AppLifecycleState.paused:
print('appLifeCycleState paused');
break;
case AppLifecycleState.suspending:
print('appLifeCycleState suspending');
break;
}
}
}
这里有一个例子:https ://github.com/flutter/flutter/blob/master/examples/layers/services/lifecycle.dart
你需要使用WidgetsBindingObserver
只有StatefulWidget持有 state 。它的生命周期如下
AppLifecycleState 如下
非活动 - 应用程序处于非活动状态并且未接收用户输入。仅限 iOS
paused - 应用程序当前对用户不可见,不响应用户输入,并且在后台运行。
resumed - 应用程序可见并响应用户输入。
暂停 - 应用程序将暂时暂停。仅限安卓
应用生命周期
对于 LifeCycle,您需要 WidgetsBindingObserver
在应用程序在前台和后台运行时使用它。
import 'package:flutter/widgets.dart';
class YourWidgetState extends State<YourWidget> 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) {
//do your stuff
}
}
}
OnResume
但就我而言,当我从一个屏幕移动到另一个屏幕时,我无法捕捉到这种情况。所以下面的代码与startActivityForResult
.
当您进行其他活动时使用此代码
Navigator.push(context,
MaterialPageRoute(builder: (context) => ProductDetails(pid: productList[index]["pid"],),
settings: RouteSettings(name: '/productdetail')),).then((value){
setState(() {
length=value;
});
debugPrint('CHECK BACK FROM DETAIL $length');
});
当你按下回
onPressed: (){Navigator.pop(context,length);}
我认为 Flutter 应用程序生命周期回调在这里不会对您有所帮助。你可以试试这个逻辑。
在第一页(导航到第二页时)
Navigator.push(context, MaterialPageRoute(builder: (context) => Page2())).then((value) {
print("Value returned form Page 2 = $value");
};
在第 2 页(导航回第 1 页时)
Navigator.pop(context, returnedValue);
生命周期回调
void main() => runApp(HomePage());
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
print("Current state = $state");
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Lifecycle")),
body: Center(child: Text("Center"),),
),
);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
}
createState():当我们创建一个有状态的小部件时,Flutter 框架会指示 createState() 方法。
@override _DeveloperLibsWidgetState createState() => _DeveloperLibsWidgetState();
2.mounted (true/false):一旦我们创建了一个State对象,框架在调用initState()方法之前通过关联一个BuildContext来挂载这个State对象。所有小部件都有一个 bool 安装属性。分配 buildContext 时变为真。
bool get mounted => _element != null;
initState():这是在类构造函数之后创建有状态小部件时调用的第一个方法。initState() 只被调用一次。它必须调用 super.initState()。
@override initState() { super.initState(); // 去做 }
didChangeDependencies():在第一次构建小部件时,在 initState() 方法之后立即调用此方法。
@protected @mustCallSuper void didChangeDependencies() {
}
build():它显示了由小部件表示的用户界面的一部分。框架在几种不同的情况下调用此方法: 在调用 initState() 方法之后。框架总是在调用 didUpdateWidget 后调用 build() 方法,在接收到 setState 的调用后更新屏幕。
@override Widget build(BuildContext context, MyButtonState state) { return Container(color: const Color(0xFF2DBD3A));
}
didUpdateWidget(Widget oldWidget):如果父小部件更改配置并且必须重建此小部件。但它正在使用相同的 runtimeType 重建,然后调用 didUpdateWidget() 方法。
@mustCallSuper @protected void didUpdateWidget(covariant T oldWidget) {
}
setState():从框架和开发人员调用此方法。我们可以更改 State 对象的内部状态,并在传递给 setState() 的函数中进行更改。
@override _DeveloperLibsWidgetState createState() => _DeveloperLibsWidgetState();
deactivate():当从小部件树中删除 State 时调用它,但它可能会在当前帧更改完成之前重新插入。
@protected @mustCallSuper void deactivate() { }
dispose():当状态对象被永久删除时调用。在这里您可以取消订阅和取消所有动画、流等。
@protected @mustCallSuper void dispose() { assert(_debugLifecycleState == _StateLifecycle.ready); 断言(() { _debugLifecycleState = _StateLifecycle.defunct; 返回 true; }()); }
您可以在Flutter扩展类中模拟onResume
和onPause
声明。确保使用 push() 或 pushNamed() 方法推送新路由。LifecycleState
/// Inherit this State to be notified of lifecycle events, including popping and pushing routes.
///
/// Use `pushNamed()` or `push()` method to track lifecycle events when navigating to another route.
abstract class LifecycleState <T extends StatefulWidget> extends State<T>
with WidgetsBindingObserver {
ResumeResult resumeResult = new ResumeResult();
bool _isPaused = false;
AppLifecycleState lastAppState = AppLifecycleState.resumed;
void onResume() {}
void onPause() {}
/// Use instead of Navigator.push(), it fires onResume() after route popped
Future<T> push<T extends Object>(BuildContext context, Route<T> route, [String source]) {
_isPaused = true;
onPause();
return Navigator.of(context).push(route).then((value) {
_isPaused = false;
resumeResult.data = value;
resumeResult.source = source;
onResume();
return value;
});
}
/// Use instead of Navigator.pushNamed(), it fires onResume() after route popped
Future<T> pushNamed<T extends Object>(BuildContext context, String routeName, {Object arguments}) {
_isPaused = true;
onPause();
return Navigator.of(context).pushNamed<T>(routeName, arguments: arguments).then((value) {
_isPaused = false;
resumeResult.data = value;
resumeResult.source = routeName;
onResume();
return value;
});
}
@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.paused) {
if (!_isPaused) {
onPause();
}
} else if (state == AppLifecycleState.resumed &&
lastAppState == AppLifecycleState.paused) {
if (!_isPaused) {
onResume();
}
}
lastAppState = state;
}
}
class ResumeResult {
dynamic data;
String source;
}
因为这里的每个人都在谈论应用程序生命周期,而不是解决 OP 提出的问题。这是问题的答案。
要求是他想从页面A打开页面B,假设从页面B中选择文件,一旦选择文件,他想回到页面A并需要处理页面A中选择的文件。就像在android中我们可以在 onActivityResult() 方法中执行此操作。以下是我们可以在颤振中实现的方式。
您可以从页面 A 打开页面 B,如下所示
Map results = await Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) {
return new PageB(title: "Choose File");
},
));
if (results != null && results.containsKey('selection')) {
setState(() {
_selection = results['selection'];
});
**//here you can do whatever you want to do with selection variable.**
}
在页面 B 中,您可以选择文件或您需要返回页面 A 的任何内容,如下所示(选择后返回文件或任何其他变量。
Navigator.of(context).pop({'selection':file});
我知道我可能会迟到一点,但会回答这个问题以防其他人需要答案,请参阅此解决方案https://stackoverflow.com/a/58504433/3037840
但我想澄清一些事情,在你的状态实现RouteAware
mixin 后的小部件,请注意:
@override
void didPushNext() { //similar to onPause
// will be called when a new route has been pushed, and the current route is no longer visible. acts similar to onPause
}
@override
void didPopNext() { //similar to onResume
// will be called when the top route has been popped off, and the current route shows up. acts similar to onResume when you are navigated back to your activity/fragment
}