Flutter(三十二)-Widget生命周期
在Flutter
中的Widget
同Android
中的Activity
和iOS
中的UIViewController
一样,也是存在生命周期的,所谓的生命周期也就是回调函数
,通过这些回调函数
可以让我们知道当前Widget
所处的状态;
生命周期的作用
当Widget
出在不同的时间状态时,会有不同的生命周期回调函数
执行,在这些回调函数
中我们可以做不同的事情:
- 初始化数据
- 变量和常量的创建
- 网络请求的发送
- 监听
Widget
的事件 - 内存的管理
- 数据或者监听者的销毁
- 定时器
TImer
的销毁
Widget的生命周期
众所周知,在Flutter
中Widget
分为:有状态
和无状态
两种,并且有状态Widget
明显要比无状态Widget
要复杂的多,那么他们的生命周期会不会有什么不同呢?
StatelessWidget的生命周期
我们在界面上加载一个简单的StatelessWidget
的页面,给页面传值title
:
很明显,我们在Flutter
中创建一个Widget
的时候,使用的都是构造方法
,比如此处的LessLifeCycleDemo
的构造方法LessLifeCycleDemo(title: "无状态Widget生命周期")
,而build
是Widget
渲染时会调用的方法;我们分别在两个方法中添加打印信息:
这是StatelessWidget
的生命周期,其相对简单;我们接下来主要介绍一下StatefulWidget
的生命周期;
StatefulWidget的生命周期
我们编写如下代码,在我们已知的生命周期方法中添加打印信息:
最终打印顺序如下:
然后点击加号按钮:
在调用setState
方法是,只有build
方法会被触发执行;
目前我们使用到的生命周期的函数还比较少,除了目前所用的,还有其他周期函数:
didChangeDependencies()
:当State
对象的依赖发生变化是被调用;典型的场景就是系统语言改变或者主题发生变化时,Flutter
框架会通知Widget
调用此回调;reassemble()
:此回调只在开发调试的过程中生效,在热重载hot reload
时被调用,在Release
模式下永远不会回调;didUpdateWidget()
:在Widget
重新构建时,Flutter
框架会调用widget.canUpdate
来检测Widget
树上同一位置的新旧两个节点,然后判断是否需要进行更新,如果返回true
,则调用此回调;widget.canUpdate
会在新旧widget
的key
和runtimeType
同时相等时返回true
;这个我们在后边渲染原理时会讲到;
deactivate()
:当State
对象从树中被移除时,会调用此回调;在某些场景下,Flutter
框架会将State
对象重新插入到树中,比如包含此State
对象的子树从树一个位置移动到另一个位置时(可通过GlobalKey
来实现)。- 如果移除后,没有重新插入到树中,则会直接调用
dispose()
方法进行销毁;
- 如果移除后,没有重新插入到树中,则会直接调用
触发build方法的场景
我们都知道build
方法在用于构建渲染Widget
是会被调用,触发build
方法有以下几个:
- 调用
initState()
之后 - 调用
didUpdateWidget()
之后 - 调用
setState()
之后 - 调用
didChangeDependencies()
之后 - 把
State
对象从树的一个位置移除后(会调用deactivate()
),又重新插入到树的其他位置之后
setState触发build的本质
我们都知道调用setState
方法将会触发build
方法的执行,那么为什么build
方法会被执行呢?我们来看一下setState
的源码:
我们可以看到setState
方法的实现中,最重要的就是_element!.markNeedsBuild()
方法,标记需要被渲染;那么_element
是什么呢?我们从上文代码中可以看到:
_element
本质上就是BuildContext
,那么我们是否可以直接使用context
调用markNeedsBuild
方法来触发build
呢?我们将代码修改如下:
运行结果:
build
方法被触发;
Android Studio中的一个bug
正常情况下,我们在编译器中打印的生命周期的信息只会执行一次,比如我们热重载的时候,方法执行如下:
但是,当我们重新执行项目的时候,却会出现下边的情况:
生命周期方法被调用了两次,这是Android Studio
的一个bug,我们可以使用Xcode来验证一下
,在Xcode
中直接运行项目是不会出现这种情况的:
转载自:https://juejin.cn/post/7036161040693854222