详解Flutter的setState更新原理和流程

//调用scheduleBuildFor方法

owner.scheduleBuildFor(this);

}

将 element 元素标记为“脏”,并把它添加到全局的“脏”链表里,以便在下一帧更新信号时更新.

  • 这里的“ ”链表是待更新的链表,更新过后就不“脏”了。

  • 由于一帧做两次更新有点低效,所以在_active=false 的时候直接返回。

那我们看看本方法最后调用的scheduleBuildFor方法。

BuildOwner 类 scheduleBuildFor方法


BuildOwner类是widget framework的管理类,它跟踪那些需要重新构建的 widget。

void scheduleBuildFor(Element element) {

if (element._inDirtyList) {

_dirtyElementsNeedsResorting = true;

return;

}

if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {

_scheduledFlushDirtyElements = true;

onBuildScheduled();//回调

}

_dirtyElements.add(element);//把element加入脏元素链表

element._inDirtyList = true;

assert(() {

if (debugPrintScheduleBuildForStacks)

debugPrint(‘…dirty list is now: $_dirtyElements’);

return true;

}());

}

把一个 element 添加到 _dirtyElements 链表,以便当WidgetsBinding.drawFrame中调用 buildScope 的时候能够重构 element。onBuildScheduled()是一个 BuildOwner 的回调。

onBuildScheduled回调在WidgetsBinding的initInstances里初始化。

mixin WidgetsBinding on BindingBase, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {

@override

void initInstances() {

super.initInstances();

_instance = this;

// 这里

buildOwner.onBuildScheduled = _handleBuildScheduled;

window.onLocaleChanged = handleLocaleChanged;window.onAccessibilityFeaturesChanged = handleAccessibilityFeaturesChanged;

SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);

SystemChannels.system.setMessageHandler(_handleSystemMessage); FlutterErrorDetails.propertiesTransformers.add(transformDebugCreator);

}

}

我们可以看到buildOwner.onBuildScheduled回调等于了_handleBuildScheduled,那现在来看看这个_handleBuildScheduled方法:

void _handleBuildScheduled() {

//调用ensureVisualUpdate

ensureVisualUpdate();

}

可以看到调用ensureVisualUpdate方法,那我们继续走下去。

SchedulerBinding类ensureVisualUpdate方法


void ensureVisualUpdate() {

switch (schedulerPhase) {

case SchedulerPhase.idle:

case SchedulerPhase.postFrameCallbacks:

//当schedulerPhase为SchedulerPhase.idle,

//SchedulerPhase.postFrameCallbacks时调用

//scheduleFrame()

scheduleFrame();

return;

case SchedulerPhase.transientCallbacks:

case SchedulerPhase.midFrameMicrotasks:

case SchedulerPhase.persistentCallbacks:

return;

}

}

分别case了SchedulerPhase 的 5 个枚举值:

状态含义idle没有正在处理的帧,可能正在执行的是 WidgetsBinding.scheduleTask,scheduleMicrotask,Timer,事件 handlers,或者其他回调等transientCallbacksSchedulerBinding.handleBeginFrame 过程, 处理动画状态更新midFrameMicrotasks处理 transientCallbacks 阶段触发的微任务(Microtasks)persistentCallbacksWidgetsBinding.drawFrame 和 SchedulerBinding.handleDrawFrame 过程,build/layout/paint 流水线工作postFrameCallbacks主要是清理和计划执行下一帧的工作

第二个case调用scheduleFrame()方法


那我们看看scheduleFrame()方法

void scheduleFrame() {

if (_hasScheduledFrame || !_framesEnabled) return;

assert(() {

if (debugPrintScheduleFrameStacks)

debugPrintStack(

label: ‘scheduleFrame() called. Current phase is $schedulerPhase.’);

return true;

}());

//调用Window 的scheduleFrame方法是一个 native 方法

window.scheduleFrame();

_hasScheduledFrame = true;

}

WidgetsFlutterBinding 混入的这些 Binding 中基本都是监听并处理 Window 对象的一些事件,然后将这些事件按照 Framework 的模型包装、抽象然后分发。可以看到 WidgetsFlutterBinding 正是粘连 Flutter engine 与上层 Framework 的“胶水”。

名解释GestureBinding提供了 window.onPointerDataPacket 回调,绑定 Framework 手势子系统,是 Framework 事件模型与底层事件的绑定入口ServicesBinding提供了 window.onPlatformMessage 回调, 用于绑定平台消息通道(message channel),主要处理原生和 Flutter 通信SchedulerBinding提供了 window.onBeginFrame 和 window.onDrawFrame 回调,监听刷新事件,绑定 Framework 绘制调度子系统PaintingBinding绑定绘制库,主要用于处理图片缓存SemanticsBinding语义化层与 Flutter engine 的桥梁,主要是辅助功能的底层支持RendererBinding提供了 window.onMetricsChanged 、window.onTextScaleFactorChanged 等回调。它是渲染树与 Flutter engine 的桥梁WidgetsBinding提供了 window.onLocaleChanged、onBuildScheduled 等回调。它是 Flutter widget 层与 engine 的桥梁

之前的文中有说过,UI 的绘制逻辑是在 Render 树中实现的,所以这里还来细看 RendererBinding 的逻辑。

RendererBinding


void initInstances() {

//监听Window对象的事件

ui.window

…onMetricsChanged = handleMetricsChanged

…onTextScaleFactorChanged = handleTextScaleFactorChanged

…onSemanticsEnabledChanged = _handleSemanticsEnabledChanged

…onSemanticsAction = _handleSemanticsAction;

//添加PersistentFrameCallback

addPersistentFrameCallback(_handlePersistentFrameCallback);

}

addPersistentFrameCallback 中添加 _handlePersistentFrameCallback 最终调用了 drawFrame 而 WidgetsBinding 重写了 RendererBinding 中的 drawFrame() 方法。最终发现我们又回到了 WidgetsBinding 这个类中,在 WidgetsBinding 中 drawFrame 的实现如下:

@override

void drawFrame() {

try {

if (renderViewElement != null)

// 重构需要更新的element

buildOwner.buildScope(renderViewElement);

super.drawFrame(); //调用RendererBinding的drawFrame()方法

buildOwner.finalizeTree();

}

}

在上面 scheduleBuildFor 方法介绍中有提到:“scheduleBuildFor 是把一个 element 添加到 _dirtyElements 链表,以便当[WidgetsBinding.drawFrame]中调用 buildScope 的时候能够重构 element。onBuildScheduled()是一个 BuildOwner 的回调”。在 drawFrame 中调用 buildOwner.buildScope(renderViewElement)更新 elements。

void buildScope(Element context, [ VoidCallback callback ]) {

while (index < dirtyCount) {

assert(_dirtyElements[index] != null);

assert(_dirtyElements[index]._inDirtyList);

assert(!_dirtyElements[index]._active || _dirtyElements[index]._debugIsInScope(context));

try {

//while 循环进行元素重构

_dirtyElements[index].rebuild();

} catch (e, stack) {

}

}

}

得出


条件判断

学习宝典

对我们开发者来说,一定要打好基础,随时准备战斗。不论寒冬是否到来,都要把自己的技术做精做深。虽然目前移动端的招聘量确实变少了,但中高端的职位还是很多的,这说明行业只是变得成熟规范起来了。竞争越激烈,产品质量与留存就变得更加重要,我们进入了技术赋能业务的时代。

不论遇到什么困难,都不应该成为我们放弃的理由!

很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从那里入手去学习,对此我针对Android程序员,我这边给大家整理了一套学习宝典!包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

【算法合集】

【延伸Android必备知识点】

【Android部分高级架构视频学习资源】
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

[外链图片转存中…(img-XXXUO48f-1715395321167)]

【算法合集】

[外链图片转存中…(img-6sRm5QwC-1715395321168)]

【延伸Android必备知识点】

[外链图片转存中…(img-k1P8GxNj-1715395321169)]

【Android部分高级架构视频学习资源】
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值