Flutter?RendererBinding作用源碼分析
分析
RendererBinding 的作用是負責render tree 和flutter engine之間的連接. 我們在啟動App的時候,首先會創(chuàng)建 PiplineOwner ,然后通過platformDispatcher去監(jiān)聽屏幕分辨率變化、系統(tǒng)文字大小變化、亮度、語義等等.最后去初始化RenderView,根據(jù)平臺去處理如幀回調、鼠標、web之類的信息.
void initInstances() { super.initInstances(); _instance = this; _pipelineOwner = PipelineOwner( onNeedVisualUpdate: ensureVisualUpdate, onSemanticsOwnerCreated: _handleSemanticsOwnerCreated, onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed, ); platformDispatcher ..onMetricsChanged = handleMetricsChanged ..onTextScaleFactorChanged = handleTextScaleFactorChanged ..onPlatformBrightnessChanged = handlePlatformBrightnessChanged ..onSemanticsEnabledChanged = _handleSemanticsEnabledChanged ..onSemanticsAction = _handleSemanticsAction; initRenderView(); _handleSemanticsEnabledChanged(); assert(renderView != null); addPersistentFrameCallback(_handlePersistentFrameCallback); initMouseTracker(); if (kIsWeb) { addPostFrameCallback(_handleWebFirstFrame); } }
PipelineOwner
這里我們著重講一下PipelineOwner, 官方描述中有這么一句話The pipeline owner manages the rendering pipeline., 也就是說 PipelineOwner幫我們管理著渲染所需要的. 我們根據(jù)PipelineOwner調用的順序依次講解下它提供的方法.
flushLayout
這個階段將計算每個渲染對象的大小和位置, 渲染對象可能會在繪制或者compositing state 的時候被標成dirty,這是什么意思呢? 讓我們回歸到代碼中
// 持有需要被布局的對象 List<RenderObject> _nodesNeedingLayout = <RenderObject>[]; { 非release包運行代碼忽略 ... try { // 如果當前的節(jié)點需要合成 while (_nodesNeedingLayout.isNotEmpty) { final List<RenderObject> dirtyNodes = _nodesNeedingLayout; _nodesNeedingLayout = <RenderObject>[]; for (final RenderObject node in dirtyNodes..sort((RenderObject a, RenderObject b) => a.depth - b.depth)) { if (node._needsLayout && node.owner == this) node._layoutWithoutResize(); } } } finally { ... } }
代碼中可以看到, 如果 _nodesNeedingLayout 中對象不為空.說明當前需要被布局,計算其大小.我們可以看到在依次處理節(jié)點時,最后一步是執(zhí)行 _layoutWithoutResize() ,這個方法調用的本質實際上也就是 performLayout(). 那么, performLayout() 做了什么呢? 如果對自定義布局有過了解, 通常我們在實現(xiàn) performLayout() 的時候.會先去 layout widget . 然后去通過position將widget 定位. 確定好widget在父widget中的相對位置.
flushCompositingBits
這個階段中, 每個渲染對象都會了解其子對象是否需要合成.在繪制的階段選擇如何實現(xiàn)視覺效果. 這里實際上也就是標記所有的子對象是否需要合成
void flushCompositingBits() { ... _nodesNeedingCompositingBitsUpdate.sort((RenderObject a, RenderObject b) => a.depth - b.depth); for (final RenderObject node in _nodesNeedingCompositingBitsUpdate) { if (node._needsCompositingBitsUpdate && node.owner == this) node._updateCompositingBits(); } _nodesNeedingCompositingBitsUpdate.clear(); ... }
flushPaint
在這個階段,我們將會真正的繪制出Layer
void flushPaint() { ... try { final List<RenderObject> dirtyNodes = _nodesNeedingPaint; _nodesNeedingPaint = <RenderObject>[]; // Sort the dirty nodes in reverse order (deepest first). for (final RenderObject node in dirtyNodes..sort((RenderObject a, RenderObject b) => b.depth - a.depth)) { ... if (node._needsPaint && node.owner == this) { if (node._layerHandle.layer!.attached) { PaintingContext.repaintCompositedChild(node); } else { node._skippedPaintingOnLayer(); } } } ... } finally { ... } }
在繪制的時候將會判斷當前的layer是否attached,如果不是attched的狀態(tài).則說明當前的layer已經(jīng)調用detach方法,因此不再需要繪制.所以會跳過繪制,執(zhí)行 _skippedPaintingOnLayer() 的方法. 如果是attached的狀態(tài),則需要調用 repaintCompositedChild() 的方法
flushSemantics
最后,如果啟用了語義. 這個階段將會編譯渲染對象的語義,這里就不過多介紹了.
initRenderView
如果說還有比較重要的方法需要講解, 那么就是 initRenderView() 這個方法了.這里將會創(chuàng)建一個 RenderView的對象作為RenderObject的根 ,同時對它進行初始化.
void initRenderView() { renderView = RenderView(configuration: createViewConfiguration(), window: window); // 準備第一幀啟動渲染通道. 這里只會調用一次. renderView.prepareInitialFrame(); }
在 PrepareInitalFrame() 中, 我們通過 scheduleInitialLayout和scheduleInitialPaint , 安排微事務隊列盡可能快的處理layout和paint.
scheduleInitialLayout
在這個階段,主要是將owner的_nodesNeedingLayout 對象中加入這個初始化的renderview.
scheduleInitialPaint
這個階段中, 我們將_layerHandle 中的layer 賦值成當前l(fā)ayer.并在owner中加入 _nodesNeedingPaint .
void scheduleInitialPaint(ContainerLayer rootLayer) { _layerHandle.layer = rootLayer; owner!._nodesNeedingPaint.add(this); }
今天的RendererBinding源碼分析就暫告一個段落了,它主要是負責了測量布局、繪制之類的方法. 作為一個入口還是有了解的必要的, 建議大家有時間可以多看看.
以上就是Flutter RendererBinding作用源碼分析的詳細內容,更多關于Flutter RendererBinding的資料請關注腳本之家其它相關文章!
相關文章
iOS UIScrollView滾動視圖/無限循環(huán)滾動/自動滾動的實例代碼
這篇文章主要介紹了iOS UIScrollView滾動視圖/無限循環(huán)滾動/自動滾動,需要的朋友可以參考下2017-02-02解析iOS應用開發(fā)中對設計模式中的抽象工廠模式的實現(xiàn)
這篇文章主要介紹了解析iOS應用開發(fā)中對設計模式中的抽象工廠模式的實現(xiàn),示例代碼為傳統(tǒng)的Objective-C,需要的朋友可以參考下2016-03-03iOS WKWebView無法處理URL Scheme和App Store鏈接的問題解決
這篇文章主要給大家介紹了關于iOS WKWebView無法處理URL Scheme和App Store鏈接的問題解決的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。2018-03-03