Flutter组件生命周期和App生命周期示例解析
顾安 人气:0引言
在Flutter开发中,所有的组件和页面都继承自Widget,所以探索页面的生命周期其实就是Widget的生命周期。 在 Flutter 中一切皆 组件,而组件又分为 StatefulWidget(有状态) 和 StatelessWidget(无状态)组件
无状态组件(StatelessWidget)
无状态组件,可以理解为将外部传入的数据转化为界面展示的内容,只会渲染一次。
有状态组件(StatefulWidget)
有状态组件,是定义交互逻辑和业务数据,可以理解为具有动态可交互的内容界面,会根据数据的变化进行多次渲染。
StatefulWidget生命周期详细分析
1. createState
当StatefulWidget被创建时立即执行createState。createState 函数执行完毕后表示当前组件已经在 Widget 树中,此时有一个非常重要的属性mounted设置为true。
2. initState
该函数为 State 初始化调用,只会被调用一次。因此,通常会在该回调中做一些一次性的操作,如执行 State 各变量的初始赋值,获取服务端数据等。
3. didChangeDependencies
该函数是在该组件依赖的 State 发生变化时会被调用。didChangeDependencies 方法调用后,组件的状态变为 dirty,立即调用 build 方法。
4. build
主要是在方法中创建各种组件,绘制到屏幕上,由于 build 会被调用多次,因此在该函数中只能做返回 Widget 相关逻辑,避免因为执行多次而导致状态异常。因此此方法可以在每一帧中调用,此方法中应该只包含构建组件的代码,不应该包含其他额外的功能,尤其是耗时任务。
5. didUpdateWidget
该函数主要是在组件重新构建,比如说热重载,父组件发生 build 的情况下,子组件该方法才会被调用,其次该方法调用之后一定会再调用本组件中的 build 方法。此方法中通常会用当前组件与前组件进行对比。Framework 调用完此方法后,会将组件设置为 dirty 状态,然后调用 build 方法,因此无需在此方法中调用 setState 方法。
6. deactivate
在组件被移除节点后会被调用,在某些情况下,框架将重新插入 State 对象到树的其他位置(例如,如果包含该树的子树 State 对象从树中的一个位置移植到另一位置),框架将会调用 build 方法来提供 State 对象适应其在树中的新位置。
7. dispose
永久移除组件,并释放组件资源。调用完 dispose后,mounted 属性被设置为 false,也代表组件生命周期的结束,此时再调用 setState 方法将会抛出异常。
8. reassemble
主要在开发阶段使用,在 debug 模式下,每次热重载都会调用该函数,因此在 debug 阶段可以在此期间增加一些 debug 代码,来检查代码问题。
App生命周期
App的生命周期的监听,在Flutter中需要通过监听器WidgetsBindingObserver监听器中的AppLifecycleState方法来是实现。
class AppLifePage extends StatefulWidget { CEAppLifePage({Key key}) : super(key: key); @override _AppLifePageState createState() => _AppLifePageState(); } // 实现WidgetsBindingObserver观察者 class _AppLifePageState extends State<AppLifePage> with WidgetsBindingObserver{ @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); //添加观察者 } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("App生命周期"),), body: Text('Flutter App 生命周期'), ); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); print("didChangeAppLifecycleState: $state"); switch (state) { case AppLifecycleState.resumed: print('应用程序可见且响应用户输入。'); break; case AppLifecycleState.paused: print('应用程序不可见且无法响应用户输入,运行在后台。'); break; case AppLifecycleState.inactive: print('应用程序处于非激活状态,无法响应用户输入。'); break; case AppLifecycleState.detached: print('应用程序仍寄存在Flutter引擎上,但与平台 View 分离。'); break; } } // 当前系统改变了一些访问性活动的回调 @override void didChangeAccessibilityFeatures() { super.didChangeAccessibilityFeatures(); print("didChangeAccessibilityFeatures"); } // 低内存回调 @override void didHaveMemoryPressure() { super.didHaveMemoryPressure(); print("didHaveMemoryPressure"); } // 用户本地设置变化时调用,如系统语言改变 @override void didChangeLocales(List<Locale> locale) { super.didChangeLocales(locale); print("didChangeLocales"); } // 应用尺寸改变时回调,例如旋转 @override void didChangeMetrics() { super.didChangeMetrics(); Size size = WidgetsBinding.instance.window.physicalSize; print("didChangeMetrics :宽:${size.width} 高:${size.height}"); } // 系统切换主题时回调 @override void didChangePlatformBrightness() { super.didChangePlatformBrightness(); print("didChangePlatformBrightness"); } // 文字系数变化 @override void didChangeTextScaleFactor() { super.didChangeTextScaleFactor(); print( "didChangeTextScaleFactor :${WidgetsBinding.instance.window.textScaleFactor}"); } @override void dispose() { super.dispose(); WidgetsBinding.instance.removeObserver(this); // 销毁观察者 } }
重点是重写 didChangeAppLifecycleState 方法,AppLifecycleState 中的状态包括:resumed、inactive、paused、detached。
resumed:应用程序可见且响应用户输入。
inactive:应用程序处于非激活状态,无法响应用户输入。在iOS上,打电话、响应TouchID请求、进入应用程序切换器或控制中心都处于此状态。在Android上,分屏应用,打电话,弹出系统对话框或其他窗口等。
pause:应用程序不可见且无法响应用户输入,运行在后台。处于此状态时,引擎将不会调用 Window.onBeginFrame 和 Window.onDrawFrame。
detached:应用程序仍寄存在Flutter引擎上,但与平台 View 分离。处于此状态的时机:引擎首次加载到附加 到一个平台 View的过程中,或者由于执行 Navigator pop ,view 被销毁。
结束语
加载全部内容