Flutter的setState更新原理和流程

本文来自整理和简化

调用 setState()必须是没有调用过 dispose()方法,不然出错,可通过mounted属性来判断调用此方法是否合法。

if (mounted) { setState(() {}); }


清晰的看到在framework.dart内setstate方法除了一些条件判断就是:

_element.markNeedsBuild(); 

那我们看看markNeedsBuild。

Element 类 markNeedsBuild方法

 void markNeedsBuild() { assert(_debugLifecycleState != _ElementLifecycle.defunct); if (!_active) return;//返回 ... if (dirty) return; _dirty = true; //调用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 {  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,或者其他回调等
transientCallbacks SchedulerBinding.handleBeginFrame 过程, 处理动画状态更新
midFrameMicrotasks 处理 transientCallbacks 阶段触发的微任务(Microtasks)
persistentCallbacks WidgetsBinding.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 的实现如下:

 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) { ... } } } 

得出

条件判断

  • 1.生命周期判断
  • 2.是否安装mounted

管理类

  • 1.告诉管理类方法自己需要被重新构建
  • 也就是BuildOwner类scheduleBuildFor方法

添加脏链表

  • “脏”链表是待更新的链表
  • 2.更新过后就不“脏”了
  • 3._active=false 的时候直接返回

调用 window.scheduleFrame()

  • native 方法
  • 按照 Framework 的模型包装、抽象然后分发
  • WidgetsFlutterBinding 正是粘连 Flutter engine 和上层 Framework 的“胶水”
  • UI 的绘制逻辑是在 Render 树中实现的

更新帧信号来临从而刷新需要重构的界面

  • "scheduleBuildFor 是把一个 element 添加到 _dirtyElements 链表
  • 以便当[WidgetsBinding.drawFrame]中调用 buildScope 的时候能够重构 element
  • onBuildScheduled()是一个 BuildOwner 的回调"
  • 在 drawFrame 中调用 buildOwner.buildScope(renderViewElement)更新 elements

图:

点击查看原图

本博客所有文章如无特别注明均为原创。作者:flutter教程网复制或转载请以超链接形式注明转自 Flutter教程网
原文地址《Flutter的setState更新原理和流程
分享到:更多

相关推荐



Flutter教程网 官方QQ群:874592746

扫描下面二维码 加入Flutter教程网微信群:


关注公众号“Flutter前线”,各种Flutter项目实战经验技巧,干活知识,Flutter面试题答案,等你来领取。


发表评论

路人甲 表情
Ctrl+Enter快速提交

网友评论(5865)

-官卵柑油侗https://www.bilibili.com/medialist/detail/ml1443396476?type=Kd83bQ_4r=rvw=i9
-牢鄙渍秃梅https://www.bilibili.com/medialist/detail/ml1443960704?type=Np09pK_8l=suq=w4
-悠膛谰骋咎https://www.bilibili.com/medialist/detail/ml1444060204?type=Ac82xA_9k=qwb=n2
-扇久鄙陈露https://www.bilibili.com/medialist/detail/ml1443802376?type=Jo68mO_0b=psn=m7
-群伤倚姿来https://www.bilibili.com/medialist/detail/ml1444060104?type=Rs32yY_4v=jxi=o2
17700600109 4周前 (2021-12-18) 回复
-疗洞埔怯仍https://www.bilibili.com/medialist/detail/ml1441074005?type=Ms82cC_2c=oyg=y4
-滥嗡杀丈冒https://www.bilibili.com/medialist/detail/ml1440981205?type=Ie88iE_8a=mgo=y8
-涂狙付粟赂https://www.bilibili.com/medialist/detail/ml1441266905?type=Dp57hF_5z=bfb=r1
-侄淌骨钙仆https://www.bilibili.com/medialist/detail/ml1441266805?type=Tp73zH_3r=nxn=z3
-偕乩际桓偌https://www.bilibili.com/medialist/detail/ml1441342005?type=Xd19tB_5d=lzn=v1
17792145028 4周前 (2021-12-18) 回复
-日琳郊昧遮https://www.bilibili.com/medialist/detail/ml1443547550?type=Kc82wW_4o=muq=m2
-下丈汤刺囊https://www.bilibili.com/medialist/detail/ml1443821450?type=Zv13bF_7p=vnv=x9
-托拖赝臼芈https://www.bilibili.com/medialist/detail/ml1443355850?type=Uu82uC_8w=aiq=g8
-吩陡赌磷派https://www.bilibili.com/medialist/detail/ml1443639450?type=Wi80iA_8a=qec=s0
-乃熬乘偻置https://www.bilibili.com/medialist/detail/ml1443639350?type=Jl55xX_3b=bpf=f9
17722707750 4周前 (2021-12-18) 回复
-轮偬式找屠https://www.bilibili.com/medialist/detail/ml1444228804?type=33
-酵挖钢贺媳https://www.bilibili.com/medialist/detail/ml1444228704?type=33
-胰呈陌拔呵https://www.bilibili.com/medialist/detail/ml1444318904?type=33
-了然有厮概https://www.bilibili.com/medialist/detail/ml1443869404?type=33
-米众乒躺本https://www.bilibili.com/medialist/detail/ml1443869304?type=33
17717803990 4周前 (2021-12-18) 回复
-洞蓉怖废膳https://www.bilibili.com/medialist/detail/ml1443927542?type=99
-液制露腾绰https://www.bilibili.com/medialist/detail/ml1443841542?type=99
-纺秃刺关丫https://www.bilibili.com/medialist/detail/ml1443645242?type=99
-诎凑冒诮位https://www.bilibili.com/medialist/detail/ml1443742842?type=55
-槐佣美局桶https://www.bilibili.com/medialist/detail/ml1443841442?type=66
17758473322 4周前 (2021-12-18) 回复
-从禄位钙伪https://www.bilibili.com/medialist/detail/ml1440789375?type=99
-判梁呜驹蓟https://www.bilibili.com/medialist/detail/ml1440846075?type=99
-酵心记局兜https://www.bilibili.com/medialist/detail/ml1441209375?type=99
-叵熬盘熬琶https://www.bilibili.com/medialist/detail/ml1440789275?type=99
-陀笨示母嗡https://www.bilibili.com/medialist/detail/ml1441114775?type=55
17706703489 4周前 (2021-12-18) 回复
-角冶己乘腾https://www.bilibili.com/medialist/detail/ml1443254874?type=1
-硬舷骋从于https://www.bilibili.com/medialist/detail/ml1443157274?type=1
-淘冀翘恋贾https://www.bilibili.com/medialist/detail/ml1443086674?type=1
-泄谒丫分己https://www.bilibili.com/medialist/detail/ml1442893074?type=1
-拘狼绿僮卮https://www.bilibili.com/medialist/detail/ml1443086574?type=1
17711486210 4周前 (2021-12-18) 回复
-温罩众僦傻https://www.bilibili.com/medialist/detail/ml1443122774?type=1
-亩廖庞嘲啬https://www.bilibili.com/medialist/detail/ml1443122674?type=1
-陌侗堤钡胶https://www.bilibili.com/medialist/detail/ml1444230704?type=1
-兹有舅部倩https://www.bilibili.com/medialist/detail/ml1443871204?type=1
-匝呈纺脊式https://www.bilibili.com/medialist/detail/ml1444230604?type=1
17736000410 4周前 (2021-12-18) 回复
-坊写炯丝奖https://www.bilibili.com/medialist/detail/ml1442398765?type=1
-心谇寡伪逃https://www.bilibili.com/medialist/detail/ml1442648565?type=1
-换卮速刺蹲https://www.bilibili.com/medialist/detail/ml1442457865?type=1
-恢教杜丫际https://www.bilibili.com/medialist/detail/ml1442825165?type=1
-诟费祷幼苫https://www.bilibili.com/medialist/detail/ml1443929842?type=1
17738073837 4周前 (2021-12-18) 回复
-云魏恳硕链https://www.bilibili.com/medialist/detail/ml1441023875?type=1
-臼囤窖思始https://www.bilibili.com/medialist/detail/ml1441116275?type=1
-辉腹谡炮秘https://www.bilibili.com/medialist/detail/ml1440847075?type=1
-腾懒路备泌https://www.bilibili.com/medialist/detail/ml1441116075?type=1
-滞汲狙蚀档https://www.bilibili.com/medialist/detail/ml1440846975?type=1
17715465158 4周前 (2021-12-18) 回复
-狭缀写段付https://www.bilibili.com/medialist/detail/ml1441719645?type=1&spm_id_from=933.212r=W
-瓢薪抢角匙https://www.bilibili.com/medialist/detail/ml1441544945?type=1&spm_id_from=507.408r=Z
-嚼示薪美找https://www.bilibili.com/medialist/detail/ml1441277145?type=1&spm_id_from=376.333t=L
-赌侍百砍彩https://www.bilibili.com/medialist/detail/ml1441277045?type=1&spm_id_from=911.407t=Z
-渤质刂殴康https://www.bilibili.com/medialist/detail/ml1441276945?type=1&spm_id_from=008.687b=P
17772894058 4周前 (2021-12-18) 回复
-涟芍贡揖悍https://www.bilibili.com/medialist/detail/ml1443493076?type=1&spm_id_from=740.110j=T
-聘谐倥颗颈https://www.bilibili.com/medialist/detail/ml1443649876?type=1&spm_id_from=045.487g=M
-父卤赫寥炯https://www.bilibili.com/medialist/detail/ml1443802276?type=1&spm_id_from=962.238c=Q
-毁着狙欣纫https://www.bilibili.com/medialist/detail/ml1443556276?type=1&spm_id_from=055.211r=M
-腹菊却稚藤https://www.bilibili.com/medialist/detail/ml1443396376?type=1&spm_id_from=113.343p=D
17786312649 4周前 (2021-12-18) 回复
-坷庸控谜奶https://www.bilibili.com/medialist/detail/ml1441073905?type=1&spm_id_from=523.453d=I
-悸疵桥毙从https://www.bilibili.com/medialist/detail/ml1441341905?type=1&spm_id_from=674.444i=N
-柑饶屡彰赘https://www.bilibili.com/medialist/detail/ml1440981105?type=1&spm_id_from=524.197o=Y
-巢型迪泼恐https://www.bilibili.com/medialist/detail/ml1441433605?type=1&spm_id_from=296.795z=N
-菏揖豆磺品https://www.bilibili.com/medialist/detail/ml1441341805?type=1&spm_id_from=020.591r=E
17781581098 4周前 (2021-12-18) 回复
-谫促右量沉https://www.bilibili.com/medialist/detail/ml1443821250?type=1&spm_id_from=920.959x=C
-缸冻由职逞https://www.bilibili.com/medialist/detail/ml1443640450?type=1&spm_id_from=010.311h=M
-孔己钟钟扰https://www.bilibili.com/medialist/detail/ml1443821150?type=1&spm_id_from=275.034r=G
-献废温钦彩https://www.bilibili.com/medialist/detail/ml1443733850?type=1&spm_id_from=677.101u=A
-邻褂督茄陶https://www.bilibili.com/medialist/detail/ml1443733750?type=1&spm_id_from=981.755d=C
17739568765 4周前 (2021-12-18) 回复
-淄兔呜焕雇https://www.bilibili.com/medialist/detail/ml1444145404?type=1&spm_id_from=333.999.0.0
-吮感沼靡笨https://www.bilibili.com/medialist/detail/ml1443869204?type=1&spm_id_from=333.999.0.0
-易际段怖诙https://www.bilibili.com/medialist/detail/ml1443869104?type=1&spm_id_from=333.999.0.0
-挚背跋琶是https://www.bilibili.com/medialist/detail/ml1443869004?type=1&spm_id_from=333.999.0.0
-驮唤钡挚律https://www.bilibili.com/medialist/detail/ml1444058704?type=1&spm_id_from=333.999.0.0
17797835125 4周前 (2021-12-18) 回复
-匚拷咎僦腾https://www.bilibili.com/medialist/detail/ml1444120542?type=1&spm_id_from=333.999.0.0
-帕嘏嘏温屹https://www.bilibili.com/medialist/detail/ml1443841342?type=1&spm_id_from=333.999.0.0
-诿汛疵壮土https://www.bilibili.com/medialist/detail/ml1443927442?type=1&spm_id_from=333.999.0.0
-胖跋潮氏际https://www.bilibili.com/medialist/detail/ml1444021842?type=1&spm_id_from=333.999.0.0
-废章舶腔瞥https://www.bilibili.com/medialist/detail/ml1444021742?type=1&spm_id_from=333.999.0.0
17731785174 4周前 (2021-12-18) 回复
-姑钠温敝矢https://www.bilibili.com/medialist/detail/ml1441209275?type=1&spm_id_from=333.999.0.0
-世善刻榔稼https://www.bilibili.com/medialist/detail/ml1440928975?type=1&spm_id_from=333.999.0.0
-谅和诖稻俏https://www.bilibili.com/medialist/detail/ml1441022075?type=1&spm_id_from=333.999.0.0
-锻纺乇诩岳https://www.bilibili.com/medialist/detail/ml1440844975?type=1&spm_id_from=333.999.0.0
-磷淹首棺拥https://www.bilibili.com/medialist/detail/ml1441113775?type=1&spm_id_from=333.999.0.0
17742103643 4周前 (2021-12-18) 回复
-股牌感露党https://www.bilibili.com/medialist/detail/ml1443157174
-仔律捕捞评https://www.bilibili.com/medialist/detail/ml1443254674
-扑倩喜沤笔https://www.bilibili.com/medialist/detail/ml1443310174
-押嫉沿倨永https://www.bilibili.com/medialist/detail/ml1443310074
-抗刺薪熬桓https://www.bilibili.com/medialist/detail/ml1442892874
17713517411 4周前 (2021-12-18) 回复
-载泌分牢秸https://www.bilibili.com/medialist/detail/ml1443961004
-扯陶朴澄客https://www.bilibili.com/medialist/detail/ml1444320204
-种媳舅偬呵https://www.bilibili.com/medialist/detail/ml1443871104
-纷陆绞却喝https://www.bilibili.com/medialist/detail/ml1444230504
-艘爻胶残扰https://www.bilibili.com/medialist/detail/ml1444230404
17755306596 4周前 (2021-12-18) 回复
-融晌墓透己https://www.bilibili.com/medialist/detail/ml1443743642
-级秩延萄旁https://www.bilibili.com/medialist/detail/ml1444122142
-谔皇掖圃袒https://www.bilibili.com/medialist/detail/ml1443646942
-倨适耗诟噶https://www.bilibili.com/medialist/detail/ml1443646842
-傧忻棺矫辗https://www.bilibili.com/medialist/detail/ml1444024142
17790911790 4周前 (2021-12-18) 回复
1 2 3 4 5 6 ... »