在 Flutter 应用开发过程中,理解生命周期管理至关重要,它们直接影响应用的性能、用户体验和开发效率。
Flutter 组件生命周期
StatelessWidget 与 StatefulWidget 的生命周期区别
在 Flutter 中,组件根据生命周期不同主要分为两种:StatelessWidget
和 StatefulWidget
。名称已经很好地表明了这两个组件的差别:一个有状态,一个无状态。
StatelessWidget
是不可变的,一旦构建完成,其内容就不会改变,除非父组件发生变化。这种组件适用于不需要维护状态的场景,如纯展示型组件。而 StatefulWidget
则允许状态变化,能够响应用户交互和数据更新。
StatelessWidget 的生命周期
StatelessWidget
是不可变的,这意味着它们的属性不能变化,所有的值都是最终的,可以理解为将外部传入的数据转化为界面展示的内容,只会渲染一次。 StatelessWidget
的生命周期相对简单,只有 build
方法。当外部依赖变化时,它会重新构建,不会保存任何内部状态。这意味着每当父组件发生变化时,整个 StatelessWidget
都会被重新创建。
StatefulWidget 的生命周期
StatefulWidget
是 Flutter 中用于构建有状态 UI 的类。StatefulWidget
主要用于需要动态更新的场景,例如用户交互、动画或异步数据处理等。它本身并不存储状态,而是通过与其关联的 State
对象来管理状态。State
是与 StatefulWidget
关联的对象,用于保存和管理 StatefulWidget
的状态信息。
每个 StatefulWidget
都会对应一个 State
对象。这种关联通过 StatefulWidget
的 createState()
方法实现,该方法返回一个 State
对象。StatefulWidget
负责定义 UI 的静态部分,如布局和初始配置。State 负责动态部分的管理维护,包括状态变化时的 UI 更新。
State
定义了 StatefulWidget
的生命周期方法,如 initState()
、didUpdateWidget()
、dispose()
等,用于在不同阶段执行特定的逻辑。所以 StatefulWidget
的生命周期,除了 createState()
方法用于创建 State
对象,其余的方法其实是 State
的生命周期方法。
createState
: 创建与StatefulWidget
相关联的状态对象,当StatefulWidget
被创建时会立即执行createState
。这个方法在StatefulWidget
的生命周期中可能会被多次调用,例如当一个StatefulWidget
同时插入到Widget
树的多个位置时。createState
函数执行完毕后表示当前组件已经在Widget
树中,此时有一个非常重要的属性mounted
被置为 true。initState
: 该函数为State
初始化时调用,只会被调用一次,因此,通常会在该方法中做一些一次性的操作,如执行State
各变量的初始赋值、订阅事件通知、获取服务端数据后调用setState
来设置State
。didChangeDependencies
: 在initState()
之后立即调用,并且当组件依赖的对象发生变化时也会被调用。这个方法用于处理依赖变化。当State
对象的依赖的InheritedWidget
关系发生变化时,该方法被调用。而这个依赖
指的就是子widget
是否使用了父widget
中InheritedWidget
的数据!如果使用了,则代表子widget
有依赖;如果没有使用则代表没有依赖。可以参考这篇文章 Flutter原理篇:didChangeDependencies什么时候被调用build
: 构建 UI 的方法,返回需要渲染的Widget
,会被多次调用。当组件需要渲染或更新时,这个方法会被调用。在该函数中不要做除创建Widget
之外的操作,会影响 UI 的渲染效率。reassemble
: 主要在开发阶段使用,在 debug 模式下,每次热重载都会调用该函数,因此在 debug 阶段可以在此期间增加一些 debug 代码,来检查代码问题。此回调在 release 模式下永远不会被调用。didUpdateWidget
: 当父组件改变其配置并需要该组件重建时调用。它接收旧组件作为参数,允许与新组件进行比较。这个方法用于处理组件配置的变化。deactivate
: 当State
对象从Widget
树中被移除或移动时被调用。如果State
对象在同一帧期间被移动了且它有GlobalKey
,那么它仍然能够被激活。dispose
: 当State
对象从Widget
树中被永久移除时调用。这个方法用于释放资源、取消订阅或执行其他清理任务。调用完dispose
后,mounted
属性被设置为 false,也代表组件生命周期的结束。
生命周期中重要的概念
mounted
: 是State
中的一个重要属性,相当于一个标识,用来表示当前组件是否在Widget
树中。在createState
方法后,mounted
会被置为 true,表示当前组件已经在树中。调用dispose
方法后,mounted
被置为 false,表示当前组件不在树中。dirty
: 表示当前组件状态的一个重要属性,下一帧时将会执行build
函数,调用setState
方法或者执行didUpdateWidget
方法后,组件的状态为dirty
。clean
: 与dirty
相对应,clean
状态下组件不会执行build
函数。
生命周期流程图
Flutter 应用生命周期
应用生命周期状态
Flutter 应用有五种生命周期状态,可见 AppLifecycleState
枚举值
detached
: 应用仍由 Flutter 引擎托管,但与任何主机视图分离。应用在初始化之前默认为此状态,并且在分离所有视图后可以处于此状态(适用于 Android、iOS 和 Web)。当应用处于此状态时,引擎在没有视图的情况下运行。此状态仅在 iOS、Android 和 Web 上会进入,但在所有平台上,它是应用开始运行之前的默认状态。一般不严谨要求的情况下,可以简单用于退出应用的状态监听。resumed
: 在所有平台上,此状态表示应用处于具有输入焦点且可见的正在运行的状态。inactive
: 应用至少一个视图是可见,但没有一个视图具有输入焦点。在 Android 和 iOS 上,inactive
可以认为它们马上会进入hidden
和paused
状态。hidden
: 应用的所有视图都处于隐藏状态。在 iOS 和 Android 上说明即将进入paused
状态,在 PC 上说明已被最小化或放置在不再可见的桌面上,在 Web 上说明在不再可见的窗口或选项卡中。在 iOS 和 Android 上,为了保持状态机在所有平台上的相同性,在从inactive
进入paused
状态之前,以及从paused
进入inactive
状态之前,合成到此状态的转换。paused
: 应用当前对用户不可见,并且不响应用户行为。当应用处于此状态时,引擎不会调用PlatformDispatcher.onBeginFrame
和PlatformDispatcher.onDrawFrame
回调。仅在 iOS 和 Android 上会进入此状态。
应用生命周期管理
WidgetsBindingObserver
WidgetsBinding.instance
在 Flutter 中用于管理应用程序的事件循环和处理各种事件,例如布局、绘制、手势和系统事件。它是 WidgetsBinding
类的一个单例实例,通过它可以访问应用程序的根 WidgetsBinding
对象。
WidgetsBinding
包含了以下常用的功能:
- 事件循环管理:
WidgetsBinding
负责管理 Flutter 应用程序的事件循环,它处理了各种事件的分发和调度。包括 build、layout、paint等事件。 - 处理系统事件:
WidgetsBinding
可以处理系统级事件,例如按键事件、触摸事件、指针事件等。 - 定时器和帧回调:
WidgetsBinding
允许注册定时器和帧回调,以便在未来的时间点执行代码或在下一帧绘制前执行代码。 - 状态管理:
WidgetsBinding
管理应用程序的生命周期状态,这有助于应用程序在不同状态下进行适当的处理。 - 媒体和屏幕分辨率信息:
WidgetsBinding
提供了访问媒体查询(MediaQuery
)和屏幕信息的方法,以便根据屏幕属性调整 UI。 - 错误处理:
WidgetsBinding
处理了 Flutter 应用程序中的异常和错误,允许注册全局错误处理程序。 - 根
BuildContext
:WidgetsBinding
提供了根BuildContext
,可以用于构建全局部件。
使用 WidgetsBindingObserver
的 didChangeAppLifecycleState
来实现应用生命周期的监听。使用的时候需要把整个 WidgetsBindingObserver
通过 mixin
引入,然后 WidgetsBinding.instance.addObserver(this)
注册监听,在 didChangeAppLifecycleState
方法中就能收到应用生命周期各个状态的回调,注意别忘记离开时要移除监听WidgetsBinding.instance.removeObserver(this)
。
AppLifecycleListener
详细介绍可以参考这篇文章 Flutter 小技巧之 3.13 全新生命周期 AppLifecycleListener
在 Flutter 3.13及其之后版本,可以通过 AppLifecycleListener
管理应用生命周期。AppLifecycleListener
是在 WidgetsBindingObserver.didChangeAppLifecycleState
的基础上进行了封装,再配合当前 lifecycleState
形成更完整的生命周期链条,对于开发者来说就是使用更方便,并且 API 相应更直观。
首先 AppLifecycleListener
是一个完整的类,所以使用它无需使用 mixin
,你只需要在使用的地方创建一个 AppLifecycleListener
对象即可。
其次,AppLifecycleListener
根据 AppLifecycleState
区分好了所有 Callback 调用,调用编排更加直观。
最后,AppLifecycleListener
可以更方便去判断和记录整个生命周期的链路变化,因为它已经帮忙封装好了回调方法。