Flutter中UI更新和渲染流程
我正在参加「掘金·启航计划」
Flutter的UI系统
说说UI系统
- UI系统:基于一个平台,在此平台上实现GUI的一个系统,这里平台特指操作系统,如Android、iOS或者Windows、macOS
- 各平台UI系统的原理是相通的,无论是Android还是iOS,将用户界面展示到屏幕的流程是相似的
Flutter UI系统
- 无论Android SDK还是iOS的UIKit 的职责都是相同的,只是语言载体和底层的系统不同而已。
- Flutter提供一套Dart API,在底层通过OpenGL这种跨平台的绘制库(内部会调用操作系统API)实现了一套代码跨多端。由于Dart API是调用操作系统API,因此性能接近原生。
- Flutter UI系统和操作系统交互的这一部分原理,简单概括就是:组合和响应式。
Android的更新渲染
- Android 原生开发中 View 更新渲染的起点是什么?—— VSync 信号
- View 的属性发生变化时,以 requestLayout 为例,内部会将自身标记为 dirty,逐级调用 parent 的 requestLayout,最后来到顶层的 ViewRoot 会向系统注册一个 vsync 信号,当下一个 VSync 来临时会调用 ViewRootImpl 的 performMeasure、performLayout、performDraw,完成 view 的重绘。
Flutter中更新流程
- Flutter 中更新流程类似,关注 Build、Layout 和 Paint 过程。UI 更新触发的条件是调用 State 对象的 setState 方法
setState链路分析
-
看一下源码
@protected void setState(VoidCallback fn) { //执行 VoidCallback 回调函数 final dynamic result = fn() as dynamic; //省略各种断言函数代码,这个后期在分析断言抛出的各种异常场景 _element.markNeedsBuild(); }
- 执行传入的回调函数,写在回调函数内的代码是执行在绘制之前的,会做一些数据的改变。
-
markNeedsBuild 代码
void markNeedsBuild() { if (!_active) return; if (dirty) return; _dirty = true; owner.scheduleBuildFor(this); }
- 调用 Element 的 markNeedsBuild 方法,内部 将自身标记,然后调用 BuildOwner 对象的 scheduleBuildFor 方法。
-
scheduleBuildFor 代码
bool _inDirtyList = false; void scheduleBuildFor(Element element) { if (element._inDirtyList) { _dirtyElementsNeedsResorting = true; return; } if (!_scheduledFlushDirtyElements && onBuildScheduled != null) { _scheduledFlushDirtyElements = true; onBuildScheduled(); } _dirtyElements.add(element); element._inDirtyList = true; }
- BuildOwner 是 Widget 的管理类,内部记录了当前的标记 Element 元素集合。_inDirtyList 是一个布尔值,作用主要是避免多次调用 scheduleBuildFor 记录脏数据。
-
整个流程梳理
- 开发者 ----> 调用 setState 方法刷新UI
- State 类 ----> 调用 void setState(VoidCallback fn) 方法 ----> 调用 _element.markNeedsBuild()
- StatefulElement 类 ----> 调用 markNeedsBuild() 方法 ----> 调用 owner.scheduleBuildFor(this)
- BuildOwner 类 ----> 调用 scheduleBuildFor(this) 方法 ----> 调用 onBuildScheduled() 方法,并且将element添加到_dirtyElements脏数据集合中
- 根据 onBuildScheduled 回调callback定位到 ----> WidgetsBinding 类 initInstances() ,在这里初始化赋值 onBuildScheduled
- WidgetsBinding 类 ----> 接着看 handleBuildScheduled ----> ensureVisualUpdate 方法 ----> 最终调用到 ensureFrameCallbacksRegistered 方法
转载自:https://juejin.cn/post/7249933985564295224