在 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 可以更方便去判断和记录整个生命周期的链路变化,因为它已经帮忙封装好了回调方法。
