<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                之前介紹的渲染流水線可以知道,這個過程大致可以分為兩段操作。第一段是從`State.setState()`到去engine那里請求一幀,第二段就是Vsync信號到來以后渲染流水線開始重建新的一幀最后送入engine去顯示。 ## setState ~~~ void setState(VoidCallback fn) { final dynamic result = fn() as dynamic; _element.markNeedsBuild(); } ~~~ ~~~ void markNeedsBuild() { if (!_active) return; if (dirty) return; _dirty = true; owner.scheduleBuildFor(this); } ~~~ 這個`BuildOwner`我們之前介紹過,它的實例是在`WidgetsBinding`初始化的時候構建的。每個`Element`的都會持有`BuildOwner`的引用 ~~~ void scheduleBuildFor(Element element) { if (element._inDirtyList) { _dirtyElementsNeedsResorting = true; return; } if (!_scheduledFlushDirtyElements && onBuildScheduled != null) { _scheduledFlushDirtyElements = true; onBuildScheduled(); } _dirtyElements.add(element); element._inDirtyList = true; } ~~~ `BuildOwner`會維護一個`_dirtyElements`列表,所有被標記為“臟”(dirty)的`element`都會被添加進去。在此之前會調用`onBuildScheduled()`。這個函數是`WidgetsBinding`初始化的時候設置給`BuildOwner`的,對應的是`WidgetsBinding._handleBuildScheduled()`。 ~~~ 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; } } ~~~ 函數`ensureVisualUpdate()`會判斷當前調度所處的狀態,如果是在`idle`(空閑)或者`postFrameCallbacks`運行狀態則調用`scheduleFrame()`。其他狀態則直接返回。下面這三個狀態正是渲染流水線運行的時候。 ~~~ void scheduleFrame() { if (_hasScheduledFrame || !_framesEnabled) return; window.scheduleFrame(); _hasScheduledFrame = true; } ~~~ `_hasScheduledFrame`標志位是為了避免重復請求。 `_framesEnabled`是代表當前app的狀態,或者說其所處的生命周期是否允許刷新界面。 ## vsync信號 Vsync信號到來之后,engin會按順序回調`window`的兩個回調函數:`onBeginFrame()`和`onDrawFrame()`。這兩個回調是`SchedulerBinding`初始化的時候設置給`window`的。對應的是`SchedulerBinding.handleBeginFrame()`和`SchedulerBinding.handleDrawFrame()`。 ## onBeginFrame 這個回調會直接走到`SchedulerBinding.handleBeginFrame()`。 ~~~ void handleBeginFrame(Duration rawTimeStamp) { ... _hasScheduledFrame = false; try { // TRANSIENT FRAME CALLBACKS _schedulerPhase = SchedulerPhase.transientCallbacks; final Map<int, _FrameCallbackEntry> callbacks = _transientCallbacks; _transientCallbacks = <int, _FrameCallbackEntry>{}; callbacks.forEach((int id, _FrameCallbackEntry callbackEntry) { if (!_removedIds.contains(id)) _invokeFrameCallback(callbackEntry.callback, _currentFrameTimeStamp, callbackEntry.debugStack); }); _removedIds.clear(); } finally { _schedulerPhase = SchedulerPhase.midFrameMicrotasks; } } ~~~ 這個函數主要是在依次回調“Transient”回調函數,這些回調函數是在調度之前設置在`SchedulerBinding`里的,這里的“Transient”意思是臨時的,或者說是一次性的。原因是這些回調函數只會被調用一次。注意看代碼里`_transientCallbacks`被置為空`Map`了。如果想在下一幀再次調用的話需要提前重新設置回調。這些回調主要和動畫有關系。也就是渲染流水線里的第一階段,動畫(Animate)階段。 在運行回調之前`_schedulerPhase`的狀態被設置為`SchedulerPhase.transientCallbacks`。回調處理完以后狀態更新至`SchedulerPhase.midFrameMicrotasks`意思是接下來會處理微任務隊列。處理完微任務以后,engine會接著回調`onDrawFrame()`。 ## onDrawFrame 這個回調會直接走到`SchedulerBinding.handleDrawFrame()`。 ~~~ void handleDrawFrame() { try { // PERSISTENT FRAME CALLBACKS _schedulerPhase = SchedulerPhase.persistentCallbacks; for (FrameCallback callback in _persistentCallbacks) _invokeFrameCallback(callback, _currentFrameTimeStamp); // POST-FRAME CALLBACKS _schedulerPhase = SchedulerPhase.postFrameCallbacks; final List<FrameCallback> localPostFrameCallbacks = List<FrameCallback>.from(_postFrameCallbacks); _postFrameCallbacks.clear(); for (FrameCallback callback in localPostFrameCallbacks) _invokeFrameCallback(callback, _currentFrameTimeStamp); } finally { _schedulerPhase = SchedulerPhase.idle; _currentFrameTimeStamp = null; } } ~~~ 在`handleDrawFrame`里按順序處理了兩類回調,一類叫“Persistent”回調,另一類叫“Post-Frame”回調。 “Persistent”字面意思是永久的。這類回調一旦注冊以后是不能取消的。主要用來驅動渲染流水線。渲染流水線的構建(build),布局(layout)和繪制(paint)階段都是在其中一個回調里的。 “Post-Frame”回調主要是在新幀渲染完成以后的一類調用,此類回調只會被調用一次。 在運行“Persistent”回調之前`_schedulerPhase`狀態變為`SchedulerPhase.persistentCallbacks`。在運行“Post-Frame”回調之前`_schedulerPhase`狀態變為`SchedulerPhase.postFrameCallbacks`。最終狀態變為`SchedulerPhase.idle`。 這里我們主要關注一個“Persistent”回調:`WidgetsBinding.drawFrame()`。這個函數是在`RendererBinding`初始化的時候加入到“Persistent”回調的。 ~~~ void drawFrame() { try { if (renderViewElement != null) buildOwner.buildScope(renderViewElement); super.drawFrame(); buildOwner.finalizeTree(); } finally { ... } } ~~~ 這里首先會調用`buildOwner.buildScope(renderViewElement)`。其入參`renderViewElement`是element tree的根節點。此時渲染流水線就進入了構建(build)階段。接下來調用了`super.drawFrame()`。這個函數定義在`RendererBinding`中。 ~~~ void drawFrame() { pipelineOwner.flushLayout(); pipelineOwner.flushCompositingBits(); pipelineOwner.flushPaint(); renderView.compositeFrame(); // this sends the bits to the GPU pipelineOwner.flushSemantics(); // this also sends the semantics to the OS. } ~~~ 可以看出渲染流水線的接力棒傳到了`pipelineOwner`的手里,渲染流水線就進入了布局(layout)階段和繪制(paint)階段。關于最后這兩個階段本篇不做詳細介紹。這里大家只要知道繪制完成以后Flutter框架最終會調用`window.render(scene)`將新幀的數據送入engine顯示到屏幕。 最后調用`buildOwner.finalizeTree();`。這個函數的作用是清理不再需要的`Element`節點。在element tree更新以后可能有些節點就不再需要掛載在樹上了,在`finalizeTree()`的時候會將這些節點及其子節點unmount。 ### 總結 1. State.setState -- Element.markNeedsBuild -- BuildOwner.scheduleBuildFor 2. BuildOwner 會維護一個`_dirtyElements`列表,scheduleBuildFor后所有被標記為“臟”(dirty)的`element`都會被添加進去 3. BuildOwner.scheduleBuildFor -- BuildOwner.onBuildScheduled -- WidgetsBinding.\_handleBuildScheduled -- SchedulerBinding.ensureVisualUpdate -- SchedulerBinding.scheduleFrame -- window.scheduleFrame() 4. window.onBeginFrame -- SchedulerBinding.handleBeginFrame -- 回調\_transientCallbacks里面回調函數 (與動畫相關) 5. window.onDrawFrame -- SchedulerBinding.handleDrawFrame() 6. handleDrawFrame內處理了兩類回調,一類叫“Persistent”回調,另一類叫“Post-Frame”回調。“Persistent”字面意思是永久的。這類回調一旦注冊以后是不能取消的。主要用來驅動渲染流水線。渲染流水線的構建(build),布局(layout)和繪制(paint)階段都是在其中一個回調里的。 “Post-Frame”回調主要是在新幀渲染完成以后的一類調用,此類回調只會被調用一次。 7. 主要關注一個“Persistent”回調:`WidgetsBinding.drawFrame()`。這個函數是在`RendererBinding`初始化的時候加入到“Persistent”回調的。 8. drawFrame中 * 首先調用buildOwner.buildScope(renderViewElement);此時構建(build)階段 * 接下來調用了`super.drawFrame()`。這個函數定義在`RendererBinding`中。渲染流水線就進入了布局(layout)階段和繪制(paint)階段。 * 最后調用`buildOwner.finalizeTree();`。這個函數的作用是清理不再需要的`Element`節點。在element tree更新以后可能有些節點就不再需要掛載在樹上了
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看