Flutter框架之生命周期

Flutter 的核心设计思想便是“一切皆 Widget”

前言:

Widget 渲染过程

通常情况下,都会用到视图树(View Tree)的概念。而 Flutter 将视图树的概念进行了扩展,把视图数据的组织和渲染抽象为三部分,即 Widget,Element 和 RenderObject。

Widget

Widget 是 Flutter 世界里对视图的一种结构化描述,你可以把它看作是前端中的“控件”或“组件”。Widget 是控件实现的基本逻辑单位,里面存储的是有关视图渲染的配置信息,包括布局、渲染属性、事件响应信息等。

Element

Element 是 Widget 的一个实例化对象,它承载了视图构建的上下文数据,是连接结构化的配置信息到完成最终渲染的桥梁。
Flutter 渲染过程,可以分为这么三步:

  • 首先,通过 Widget 树生成对应的 Element 树;
  • 然后,创建相应的 RenderObject 并关联到 Element.renderObject 属性上;
  • 最后,构建成 RenderObject 树,以完成最终的渲染。

RenderObject

RenderObject 是主要负责实现视图渲染的对象。

Flutter 通过控件树(Widget 树)中的每个控件(Widget)创建不同类型的渲染对象,组成渲染对象树。
渲染对象树在 Flutter 的展示过程分为四个阶段,即布局、绘制、合成和渲染。 其中,布局和绘制在 RenderObject 中完成,Flutter 采用深度优先机制遍历渲染对象树,确定树中各个对象的位置和尺寸,并把它们绘制到不同的图层上。绘制完毕后,合成和渲染的工作则交给 Skia 搞定

扩展知识:

React:JSX->虚拟DOM->浏览器DOM
React Native:JSX->虚拟DOM->Android/iOS原生控件
flutter:Widget->Element(类似虚拟DOM,只是一种数据结构)-> RenderObject 交给底层渲染
Element是可复用的,只要Widget前后类型一样。比如Widget是蓝色的,重建后变红色了,Element是会复用的。所以是多个Widget(销毁前后)会对应一个Element。而Widget是不可变的,一旦改变就会销毁重建。

————————————————

state生命周期

————————————————

widget是immutable的,发生变化的时候需要重建,所以谈不上状态。StatefulWidget 中的状态保持其实是通过State类来实现的。State拥有一套自己的生命周期,下面做一个简单的介绍。


State 的生命周期可以分为 3 个阶段:

  • 创建(插入视图树)
  • 更新(在视图树中存在)
  • 销毁(从视图树中移除)

生命周期状态图.png

创建

State 初始化时会依次执行 :构造方法 -> initState -> didChangeDependencies -> build,随后完成页面渲染。

构造函数(construction)

调用次数:1次
用处:

  • 页面传参

  • 初始化UI配置

    构造方法是 State 生命周期的起点,Flutter 会通过调用 StatefulWidget.createState() 来创建一个 State。我们可以通过构造方法,来接收父 Widget 传递的初始化 UI 配置数据。这些配置数据,决定了 Widget 最初的呈现效果。
    这个函数严格意义上来讲不属于生命周期的一部分,因为这个时候State的widget属性为空,无法在构造函数中访问widget的属性 。但是构造函数必然是要第一个调用的。可以在这一部分接收前一个页面传递过来的数据。

initState

调用次数:1次
用处:

  • 初始化变量

    当State 对象被插入渲染树的时候调用,这个函数在生命周期中只调用一次。所以我们可以在这里做一些初始化工作,比如初始化State的变量、状态变量设定默认值。

didChangeDependencies

调用次数:多次

  • 初始化时,在initState()之后立刻调用
  • 当依赖的InheritedWidget rebuild,会触发此接口被调用

Called when a dependency of this [State] object changes.

build

调用次数:多次

作用是构建视图。经过以上步骤,Framework 认为 State 已经准备好了,于是调用 build。我们需要在这个函数中,根据父 Widget 传递过来的初始化配置数据,以及 State 的当前状态,创建一个 Widget 然后返回。
Called whenever the widget configuration changes.


更新

Widget 的状态更新,主要由 3 个方法触发:

  • setState
  • didchangeDependencies
  • didUpdateWidget

setState:我们最熟悉的方法之一。当状态数据发生变化时,我们总是通过调用这个方法告诉 Flutter:“我这儿的数据变啦,请使用更新后的数据重建 UI!”;当setState触发的时候build会再次被调用。

didChangeDependencies:State 对象的依赖关系发生变化后,Flutter 会回调这个方法,随后触发组件构建。哪些情况下 State 对象的依赖关系会发生变化呢?典型的场景是,系统语言 Locale 或应用主题改变时,系统会通知 State 执行 didChangeDependencies 回调方法。

didUpdateWidget:当 Widget 的配置发生变化时,比如,父 Widget 触发重建(即父 Widget 的状态发生变化时),热重载时,系统会调用这个函数。

一旦这三个方法被调用,Flutter 随后就会销毁老 Widget,并调用 build 方法重建 Widget。


销毁(组件移除)

组件移除,例如页面销毁的时候会依次执行:deactivate > dispose

deactivate
调用次数:多次
Called when this object is removed from the tree.

在dispose之前,会调用这个函数。实测在组件可见状态变化的时候会调用,当组件卸载时也会先一步dispose调用。值得注意的是,页面切换时,由于 State 对象在视图树中的位置发生了变化,需要先暂时移除后再重新添加,重新触发组件构建,因此这个函数也会被调用。

dispose
调用次数:1次
Called when this object is removed from the tree permanently.

一旦到这个阶段,组件就要被销毁了,这个函数一般会移除监听,清理环境。


图例.jpg
 // 初始化状态,只执行一次
 void initState() { }
 
 // 当widget依赖的对象发生变化时调用,例如全局的主题或语言
 void didChangeDependencies() { }
 
 // 当widget重新构建时调用,根据canUpdate方法判断
 void didUpdateWidget(covariant T oldWidget) { }
 
 // 构建UI
 void build() { }
 
 // 调试模式下,热重载执行,Release模式不会执行
 void reassemble() { }
  
 // 当widget被移除时调用
 void deactivate() { }
 
 // 当widget被永久移除时,可以做释放资源
 void dispose() { }

————————————————

App 生命周期

————————————————
在原生开发中,我们可以通过重写 Activity、ViewController 生命周期回调方法,或是注册应用程序的相关通知,来监听 App 的生命周期并做相应的处理。而在 Flutter 中,我们可以利用 WidgetsBindingObserver 类,来实现同样的需求。

通过继承WidgetsBindingObserver,该类中存在一个回调方法didChangeAppLifecycleState,用于表示当前应用状态改变。(当然WidgetsBindingObserver 中还有其他很多状态回调,比如一个route 被push 或者pop,比如横竖屏变化,比如用户locales切换,是否存在内存压力,辅助功能切换等。)

常用状态包含如下几个:

名称 状态
resumed 可见并能响应用户的输入
inactive 处在并不活动状态,无法处理用户响应
paused 不可见并不能响应用户的输入,但是在后台继续活动中
abstract class WidgetsBindingObserver {
  //页面pop
  Future didPopRoute() => Future.value(false);
  //页面push
  Future didPushRoute(String route) => Future.value(false);
  //系统窗口相关改变回调,如旋转
  void didChangeMetrics() { }
  //文本缩放系数变化
  void didChangeTextScaleFactor() { }
  //系统亮度变化
  void didChangePlatformBrightness() { }
  //本地化语言变化
  void didChangeLocales(List locale) { }
  //App生命周期变化
  void didChangeAppLifecycleState(AppLifecycleState state) { }
  //内存警告回调
  void didHaveMemoryPressure() { }
  //Accessibility相关特性回调
  void didChangeAccessibilityFeatures() {}
}

你可能感兴趣的:(Flutter框架之生命周期)