搜文章
推荐 原创 视频 Java开发 iOS开发 前端开发 JavaScript开发 Android开发 PHP开发 数据库 开发工具 Python开发 Kotlin开发 Ruby开发 .NET开发 服务器运维 开放平台 架构师 大数据 云计算 人工智能 开发语言 其它开发
Lambda在线 > Android部落格 > flutter setState机制

flutter setState机制

Android部落格 2020-05-20

个人网站:chengang.plus

1、定义

setState方法只能定义在State类中,执行这个方法之后,能够更新State限定的StatefulWidget及其子Widget树。

在StatefulWidget执行createElement方法创建StatefulElement对象的时候,会回调到StatefulWidget的createState方法,也就回到了我们自定义Widget继承StatefulWidget的createState方法,从而创建了一个State对象。

这个State持有一个_element和一个_widget对象。

2、State中执行

在State类中定义了setState方法:

@protectedvoid setState(VoidCallback fn) { final dynamic result = fn() as dynamic; _element.markNeedsBuild();}

2.1 标记为dirty

先执行我们的闭包函数fn(),然后执行markNeedsBuild,定义在Element类中:

void markNeedsBuild() { if (!_active) return; if (dirty) return; _dirty = true; owner.scheduleBuildFor(this);}

2.2 BuildOwner调度重建

当前Element节点被标记为dirty,同时调用owner的scheduleBuildFor方法,owner是BuildOwner类型,看看scheduleBuildFor方法:

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。这个owner最开始被初始化的地方在WidgetsBinding的initInstances方法中,随后初始化了onBuildScheduled方法,对应执行的是_handleBuildScheduled,定义在WidgetsBinding类中,看看这个方法:

void _handleBuildScheduled() { ensureVisualUpdate();}

ensureVisualUpdate方法定义在SchedulerBinding类中:

void ensureVisualUpdate() { switch (schedulerPhase) { case SchedulerPhase.idle: case SchedulerPhase.postFrameCallbacks: scheduleFrame(); return; case SchedulerPhase.transientCallbacks: case SchedulerPhase.midFrameMicrotasks: case SchedulerPhase.persistentCallbacks: return; }}

2.2 调度绘制

在提交下一帧绘制的时候会调用到scheduleFrame方法,提交给引擎绘制,看看scheduleFrame方法,也定义在SchedulerBinding类中:

void scheduleFrame() { if (_hasScheduledFrame || !framesEnabled) return; ensureFrameCallbacksRegistered(); window.scheduleFrame();//native 'Window_scheduleFrame' _hasScheduledFrame = true;}
@protectedvoid ensureFrameCallbacksRegistered() { window.onBeginFrame ??= _handleBeginFrame; window.onDrawFrame ??= _handleDrawFrame;}

提交给引擎绘制之后,会收到onDrawFrame的回调,最终执行到_handleDrawFrame方法中,对应的是handleDrawFrame方法,定义在SchedulerBinding类中:

void handleDrawFrame() { Timeline.finishSync(); // end the "Animate" phase try { // PERSISTENT FRAME CALLBACKS _schedulerPhase = SchedulerPhase.persistentCallbacks; for (final FrameCallback callback in _persistentCallbacks) _invokeFrameCallback(callback, _currentFrameTimeStamp);  // POST-FRAME CALLBACKS _schedulerPhase = SchedulerPhase.postFrameCallbacks; final List<FrameCallback> localPostFrameCallbacks = List<FrameCallback>.from(_postFrameCallbacks); _postFrameCallbacks.clear(); for (final FrameCallback callback in localPostFrameCallbacks) _invokeFrameCallback(callback, _currentFrameTimeStamp); } finally { _schedulerPhase = SchedulerPhase.idle; Timeline.finishSync(); // end the Frame _currentFrameTimeStamp = null; }}

这个_persistentCallbacks在之前的章节有讲到过,在RendererBinding的initInstances方法中添加了一个回调到这个List中,对应的是RendererBinding的drawFrame方法,对对应的节点进行绘制渲染操作。

3、绘制

3.1 开始绘制渲染

但是在WidgetsBinding类中,也覆写了drawFrame方法。在之前的绘制过程章节,可以看到WidgetsBinding相当于是继承了RendererBinding接口,所以先调用WidgetsBinding中的drawFrame方法:

@overridevoid drawFrame() { TimingsCallback firstFrameCallback; if (_needToReportFirstFrame) { firstFrameCallback = (List<FrameTiming> timings) { if (!kReleaseMode) { developer.Timeline.instantSync('Rasterized first useful frame'); developer.postEvent('Flutter.FirstFrame', <String, dynamic>{}); } SchedulerBinding.instance.removeTimingsCallback(firstFrameCallback); firstFrameCallback = null; _firstFrameCompleter.complete(); }; // Callback is only invoked when [Window.render] is called. When // [sendFramesToEngine] is set to false during the frame, it will not // be called and we need to remove the callback (see below). SchedulerBinding.instance.addTimingsCallback(firstFrameCallback); }  try { if (renderViewElement != null) buildOwner.buildScope(renderViewElement); super.drawFrame(); buildOwner.finalizeTree(); } finally { } if (!kReleaseMode) { if (_needToReportFirstFrame && sendFramesToEngine) { developer.Timeline.instantSync('Widgets built first useful frame'); } } _needToReportFirstFrame = false; if (firstFrameCallback != null && !sendFramesToEngine) { SchedulerBinding.instance.removeTimingsCallback(firstFrameCallback); }}

看看这里的buildScope方法,定义在BuildOwner方法中:

void buildScope(Element context, [ VoidCallback callback ]) { if (callback == null && _dirtyElements.isEmpty) return; Timeline.startSync('Build', arguments: timelineWhitelistArguments); _dirtyElements.sort(Element._sort); _dirtyElementsNeedsResorting = false; int dirtyCount = _dirtyElements.length; int index = 0; while (index < dirtyCount) { try { _dirtyElements[index].rebuild(); } catch (e, stack) { }finally { for (final Element element in _dirtyElements) { element._inDirtyList = false; } _dirtyElements.clear(); _scheduledFlushDirtyElements = false; _dirtyElementsNeedsResorting = null; Timeline.finishSync(); } }}

_dirtyElements列表,先从深到浅排序,之后遍历,遍历的过程中执行rebuild方法,此时将所有标记为dirty的Element节点依次执行rebuild,preformRebuild,build,updateChild,update方法,执行界面更新。

当然了,这些build,update操作完成之后,后续会将需要绘制的RenderObject添加到需要layout的列表中,等待绘制渲染。

所有绘制完成之后将_dirtyElements列表清空,_inDirtyList标记位置为false。

3.2 提交给引擎绘制渲染

看看super.drawFrame(),这里就执行到了RendererBinding类中,定义如下:

void drawFrame() { pipelineOwner.flushLayout(); pipelineOwner.flushCompositingBits(); pipelineOwner.flushPaint(); if (sendFramesToEngine) { renderView.compositeFrame(); // this sends the bits to the GPU pipelineOwner.flushSemantics(); // this also sends the semantics to the OS. _firstFrameSent = true; }}

这里就是将最终需要绘制渲染的画面提交给引擎绘制的地方了,绘制完成之后就在界面显示更新后的视图了。


版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《flutter setState机制》的版权归原作者「Android部落格」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458

文章来源: 阅读原文

相关阅读

关注Android部落格微信公众号

Android部落格微信公众号:chuck2Dev

Android部落格

手机扫描上方二维码即可关注Android部落格微信公众号

Android部落格最新文章

精品公众号随机推荐