個(gè)人網(wǎng)站:chengang.plus
1、定義
setState方法只能定義在State類(lèi)中,執(zhí)行這個(gè)方法之后,能夠更新State限定的StatefulWidget及其子Widget樹(shù)。
在StatefulWidget執(zhí)行createElement方法創(chuàng)建StatefulElement對(duì)象的時(shí)候,會(huì)回調(diào)到StatefulWidget的createState方法,也就回到了我們自定義Widget繼承StatefulWidget的createState方法,從而創(chuàng)建了一個(gè)State對(duì)象。
這個(gè)State持有一個(gè)_element和一個(gè)_widget對(duì)象。
2、State中執(zhí)行
在State類(lèi)中定義了setState方法:
@protected
void setState(VoidCallback fn) {
final dynamic result = fn() as dynamic;
_element.markNeedsBuild();
}
2.1 標(biāo)記為dirty
先執(zhí)行我們的閉包函數(shù)fn(),然后執(zhí)行markNeedsBuild,定義在Element類(lèi)中:
void markNeedsBuild() {
if (!_active)
return;
if (dirty)
return;
_dirty = true;
owner.scheduleBuildFor(this);
}
2.2 BuildOwner調(diào)度重建
當(dāng)前Element節(jié)點(diǎn)被標(biāo)記為dirty,同時(shí)調(diào)用owner的scheduleBuildFor方法,owner是BuildOwner類(lèi)型,看看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用來(lái)管理那些需要更新的Widget。這個(gè)owner最開(kāi)始被初始化的地方在WidgetsBinding的initInstances方法中,隨后初始化了onBuildScheduled方法,對(duì)應(yīng)執(zhí)行的是_handleBuildScheduled,定義在WidgetsBinding類(lèi)中,看看這個(gè)方法:
void _handleBuildScheduled() {
ensureVisualUpdate();
}
ensureVisualUpdate方法定義在SchedulerBinding類(lèi)中:
void ensureVisualUpdate() {
switch (schedulerPhase) {
case SchedulerPhase.idle:
case SchedulerPhase.postFrameCallbacks:
scheduleFrame();
return;
case SchedulerPhase.transientCallbacks:
case SchedulerPhase.midFrameMicrotasks:
case SchedulerPhase.persistentCallbacks:
return;
}
}
2.2 調(diào)度繪制
在提交下一幀繪制的時(shí)候會(huì)調(diào)用到scheduleFrame方法,提交給引擎繪制,看看scheduleFrame方法,也定義在SchedulerBinding類(lèi)中:
void scheduleFrame() {
if (_hasScheduledFrame || !framesEnabled)
return;
ensureFrameCallbacksRegistered();
window.scheduleFrame();//native 'Window_scheduleFrame'
_hasScheduledFrame = true;
}
@protected
void ensureFrameCallbacksRegistered() {
window.onBeginFrame ??= _handleBeginFrame;
window.onDrawFrame ??= _handleDrawFrame;
}
提交給引擎繪制之后,會(huì)收到onDrawFrame的回調(diào),最終執(zhí)行到_handleDrawFrame方法中,對(duì)應(yīng)的是handleDrawFrame方法,定義在SchedulerBinding類(lèi)中:
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;
}
}
這個(gè)_persistentCallbacks在之前的章節(jié)有講到過(guò),在RendererBinding的initInstances方法中添加了一個(gè)回調(diào)到這個(gè)List中,對(duì)應(yīng)的是RendererBinding的drawFrame方法,對(duì)對(duì)應(yīng)的節(jié)點(diǎn)進(jìn)行繪制渲染操作。
3、繪制
3.1 開(kāi)始繪制渲染
但是在WidgetsBinding類(lèi)中,也覆寫(xiě)了drawFrame方法。在之前的繪制過(guò)程章節(jié),可以看到WidgetsBinding相當(dāng)于是繼承了RendererBinding接口,所以先調(diào)用WidgetsBinding中的drawFrame方法:
@override
void 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列表,先從深到淺排序,之后遍歷,遍歷的過(guò)程中執(zhí)行rebuild方法,此時(shí)將所有標(biāo)記為dirty的Element節(jié)點(diǎn)依次執(zhí)行rebuild,preformRebuild,build,updateChild,update方法,執(zhí)行界面更新。
當(dāng)然了,這些build,update操作完成之后,后續(xù)會(huì)將需要繪制的RenderObject添加到需要layout的列表中,等待繪制渲染。
所有繪制完成之后將_dirtyElements列表清空,_inDirtyList標(biāo)記位置為false。
3.2 提交給引擎繪制渲染
看看super.drawFrame(),這里就執(zhí)行到了RendererBinding類(lèi)中,定義如下:
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;
}
}
這里就是將最終需要繪制渲染的畫(huà)面提交給引擎繪制的地方了,繪制完成之后就在界面顯示更新后的視圖了。