颤动中的生命周期

是否颤动有一个方法,如 Activity.resume(),可以告诉开发人员的用户已经回到活动。

当我从网页 B 中选取数据并返回到网页 A 时,我怎样才能让网页 A 知道数据已经准备好了。

141631 次浏览

这里有一个例子: https://github.com/flutter/flutter/blob/master/examples/layers/services/lifecycle.dart

你需要使用 WidgetsBindingObserver

  1. 返回文章页面 当框架被指示构建一个状态部件时,它会立即调用 createState()

  2. mounted是正确的:createState创建状态类时,将为该状态分配一个 buildContextbuildContext是小部件树中放置这个小部件的位置,这个位置过于简化了。这里有一个更长的解释。 所有小部件都具有 bool this.mounted属性。当分配 buildContext时,它变为 true。卸载小部件时调用 setState是一个错误。

  3. 返回文章页面 这是创建小部件时调用的第一个方法(当然是在类构造函数之后)initState只调用一次。它必须调用 super.initState()

  4. 返回文章页面 在第一次构建小部件时,在 initState之后立即调用此方法。

  5. 返回文章页面 此方法经常被调用。它是必需的,并且必须返回一个 Widget。

  6. 返回文章页面 如果父窗口小部件发生更改并必须重新构建此窗口小部件(因为它需要为其提供不同的数据) ,但是正在使用相同的 runtimeType进行重新构建,则调用此方法。 这是因为 Flutter 正在重新利用这个长期存在的国家。在这种情况下,您可能需要像在 initState中那样再次初始化某些数据。

  7. 返回文章页面 通常从框架本身和开发人员调用此方法。它用于通知框架数据已更改

  8. 返回文章页面 当从树中移除 State 时调用禁用,但它可能在当前帧更改完成之前被重新插入。此方法之所以存在,基本上是因为可以将 State 对象从树中的一个点移动到另一个点。

  9. 返回文章页面 在删除 State 对象时调用 dispose(),这是永久的。此方法是您应该取消订阅和取消所有动画,流等。

  10. mounted为假: 状态对象永远不能重新挂载,如果调用 setState,将引发错误。

我不认为颤动应用程序生命周期回调将在这里帮助你。你可以尝试这个逻辑。

在第一页(导航到第二页时)

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();
}
}

应用程序生命周期

对于 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);}

enter image description here 构造函数

这个函数不是生命周期的一部分,因为这一次,如果您想访问构造函数中的小部件属性,则小部件属性的 State 是空的。但是构造函数必须是第一个调用的。

创建状态

当指示 Flutter 构建一个 StatefulWidget时,它立即调用 createState()

Init State

当此对象插入到树中时调用。

在调用时插入呈现树时,此函数在生命周期中只调用一次。这里可以进行一些初始化,比如初始化 State 变量。

SetState

通常从 Flutter 框架本身和开发人员调用 setState()方法。

依赖性

当此[ State ]对象的依赖项更改时调用。

插件

每当小部件配置更改时调用。

解除

当此对象从树中移除时调用。 在释放之前,我们将调用这个函数。

处理掉

当此对象从树中永久移除时调用。

生命周期状态

当系统将应用程序置于后台或将应用程序返回到前台时调用。

这里有一个很好的详细文档: 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;
}
}


}
 

只有 状态部件保持状态。 它的生活方式如下

  • CreateState () : 当我们构建一个新的状态控件时,这个控件会立即调用 createState () ,并且这个重写方法必须存在
  • InitState () : 它是创建 Widget 之后调用的第一个方法
  • Did ChangeDependency () : 在第一次构建小部件时,在 initState ()之后立即调用此方法
  • Build () : 在 did ChangeDependency ()之后调用。所有的图形用户界面都是在这里渲染的,每次需要渲染的时候都会被调用
  • DiUpdateWidget () : 一旦父 Widget 做了更改并需要重新绘制 UI,就会调用它
  • Deactive () : 每当框架从树中移除此 State 对象时,都会调用此方法
  • 从树中永久删除此对象及其状态并且永远不会再生成时,调用 pose ()。

AppLificycleState 如下所示

  • Inactive-应用程序处于非活动状态 接收用户输入

  • 暂停-应用程序当前对用户不可见,而不是 响应用户输入,并在后台运行。

  • 可见并响应用户输入的应用程序。

  • 暂停-申请将暂停。 Android 只有

  1. CreateState () : 当我们创建一个有状态小部件时,Flutter 框架指示 createState ()方法。

    @ 覆盖 _ DeveloperLibsWidgetState createState () = > _ DeveloperLibsWidgetState () ;

2.挂载(真/假): 一旦我们创建了一个 State 对象,框架在调用 initState ()方法之前通过将 State 对象与 BuildContext 关联来挂载它。所有小部件都有一个 bool 挂载属性。当 buildContext 被分配时,它变为 true。

bool get mounted => _element != null;
  1. InitState () : 这是在类构造函数之后创建有状态小部件时调用的第一个方法。InitState ()只调用一次。它必须调用 super.initState ()。

    @ 覆盖 InitState (){ InitState () ; //待办事项 }

  2. Did ChangeDependency () : 在第一次构建小部件时,在 initState ()方法之后立即调用此方法。

    @ protected @ MustCallSuper Void did ChangeDependency (){

    }

  3. Build () : 它显示由小部件表示的用户界面部分。这个框架在几种不同的情况下调用这个方法: 在调用 initState ()方法之后。 框架总是在调用 diUpdateWidget 之后调用 build ()方法 在接收到 setState 更新屏幕的调用之后。

    @ 覆盖 小部件生成(BuildContext 上下文,MyButtonState 状态){ 返回容器(颜色: const Color (0xFF2DBD3A)) ;
    }

  4. DiUpdateWidget (Widget oldWidget) : 如果父部件更改了配置并且必须重新构建此部件。但是它是用相同的 runtimeType 重新构建的,然后调用 did UpdateWidget ()方法。

    @ MustCallSuper @ protected Void diUpdateWidget (协变 T oldWidget){

    }

  5. SetState () : 从框架和开发人员调用此方法。我们可以更改 State 对象的内部状态,并对传递给 setState ()的函数进行更改。

    @ 覆盖 _ DeveloperLibsWidgetState createState () = > _ DeveloperLibsWidgetState () ;

  6. Deactive () : 当从小部件树中删除 State 时调用,但是它可能在当前帧更改完成之前被重新插入。

    @ protected @ MustCallSuper (){}

  7. 释放() : 在永久删除 State 对象时调用这个函数。在这里您可以取消订阅和取消所有动画,流等。

    @ protected @ MustCallSuper 无效处置() Assert (_ debugLifecycleState = = _ StateLifecycle.ready) ; Asser((){ _ debugLifcycleState = _ StateLifcycle.defunction; 返回 true; }()) ; }

因为这里的每个人都在谈论应用程序生命周期,而没有回答 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});

您可以在扩展 LifecycleState类的 颤动中模拟 onResumeonPause状态。确保使用 push ()或 pushName ()方法推送新路由。

/// 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;
}

我知道我可能会晚一点但我会回答这个问题以防有人需要答案, 请参考此解决方案 https://stackoverflow.com/a/58504433/3037840 但是我想澄清一些事情,在实现 RouteAware混合后的有状态小部件中,请注意:

@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
}