Texture的異步渲染和佈局引擎

  • Texture的簡介 (What)node

  • 爲何要使用Texture (Why)git

  • Texture的做者 (Who)github

  • Node的異步繪製如何實現 (How)緩存

  • Node的異步渲染(Runloop任務分發)如何實現 (How)數據結構

  • Texture的佈局引擎 (How)架構

  • Texture的使用能帶來什麼收益 (How Much)併發

texture簡介:框架

Texture(原名AsyncDisplayKit)是FaceBook開源的一款可以保持界面流暢的框架。創建在UIKit之上,能夠保持最複雜的用戶界面的流暢和響應。(smooth and responsive)異步

Texture總體架構oop

Node:對UIView和CALayer的抽象

Node Containers:node容器,負責加載渲染node

Layout Engineer:node佈局

Texture節點容器與UIKit

Texture節點子類與UIKit

Texture節點子類繼承樹

爲何要使用Texture

  • 佈局計算、解碼、繪製,異步併發執行

  • Runloop任務分發(異步渲染)

  • 聲明式佈局系統

  • 圖層預合成

  • 深度優化列表性能(智能預加載)

Texture:圖層預合成

有時一個 layer 會包含不少 sub-layer,而這些 sub-layer 並不須要響應觸摸事件,也不須要進行動畫和位置調整。ASDK 爲此實現了一個被稱爲 pre-composing 的技術,能夠把這些 sub-layer 合成渲染爲一張圖片。開發時,ASNode 已經替代了 UIView 和 CALayer;直接使用各類 Node 控件並設置爲 layer backed 後,ASNode 甚至能夠經過預合成來避免建立內部的 UIView 和 CALayer。

經過這種方式,把一個大的層級,經過一個大的繪製方法繪製到一張圖上,性能會得到很大提高。CPU 避免了建立 UIKit 對象的資源消耗,GPU 避免了多張 texture 合成和渲染的消耗,更少的 bitmap 也意味着更少的內存佔用。

圖層預合成

Texture:智能預加載

全部節點都持有當前界面狀態interfaceState,由ASRangeController控制屬性值更新,在全部節點容器的內部建立和維護。

智能預加載

  • Preload:節點還不可見,這時節點收集外部源(API或磁盤數據)

  • Display:節點開始渲染,包括文本的光柵化以及圖像解碼等

  • Visible:節點可見,在屏幕上至少擁有一個像素

Texture的做者

Scott Goodson

ASDK 的做者是 Scott Goodson ,他曾經在蘋果工做,負責 iOS 的一些內置應用的開發,好比股票、計算器、地圖、鐘錶、設置、Safari 等,固然他也參與了 UIKit framework 的開發。後來他加入 Facebook 後,負責 Paper 的開發,建立並開源了 AsyncDisplayKit。目前他在 Pinterest 和 Instagram 負責 iOS 開發和用戶體驗的提高等工做。

Node的異步繪製如何實現

UIKit的繪製機制圖解

CALayer的display方法由系統調用,用來更新layer的內容,若是layer有delegate對象,那麼display方法將嘗試調用delegate的displayLayer:方法來更新layer的內容。若是delegate沒有實現displayLayer:方法,則這個方法會建立一個backing store來保存原來的內容,而後調用layer的drawInContext:方法來填充back store。最後以新的backing store替換layer的先前內容達到更新layer的目的。一般UIKit中CALayer的delegate是UIView對象。

有兩種方式來自定義CALayer的內容,一種是直接設置CALayer的contents屬性來建立寄宿圖;另外一種是經過實現CALayer的delegate方法,能夠用於直接對CALayer進行操做。

Node的異步繪製

UIKit

Texture

ASDisplayNode是整個Texture的基石,也是頁面異步繪製的核心,其持有UIView和CALayer兩種對象,均由node本身生成並管理。

異步繪製時序圖

 

_ASDisplayLayer經過重寫了CALayer的display方法來自定義CALayer的寄宿圖屬性。_ASDisplayLayer與ASDisplayNode的關係相似於CALayer與UIView的關係。

Node的異步繪製流程

  1. 獲取node的displayBlock,也就是負責根據node的視圖層級獲得須要顯示的內容的繪製任務。

  2. 生成Node繪製完成後的回調completeBlock。

  3. 根據displaysAsynchronously屬性來判斷是否須要異步繪製,若是是異步的,則將displayBlock提交至_ASAsyncTransaction中,不然當即執行displayBlock。

Node的異步渲染

  1. 尋找Layer相關的ASAsyncTransaction。

  2. 將displayBlock和completeBlock添加至ASAsyncTransaction。

  3. 利用ASAsyncTransactionQueue進行調度。

  4. mainRunloop在開始sleep和exit的時候提交ASAsyncTransaction。

  5. ASAsyncTransaction在提交的時候回調completeBlock,完成layer寄宿圖的賦值。

<ps:displayblock執行不在主線程,completeblock執行在主線程!>

底層信號驅動原理

iOS的顯示系統由VSync信號驅動的,VSync信號由硬件時鐘生成,每秒鐘發出60次。iOS圖形服務接收到VSync信號後,會經過IPC通知到APP內。APP的Runloop在啓動後會註冊對應CFRunloopSource經過mach_port接收傳過來的時鐘信號通知,隨後source的回調會驅動整個App的動畫與顯示。

Runloop任務分發 ->CoreAnimation

CA在Runloop中註冊了一個Observer,監聽了BeforeWaiting和Exit事件,優先級低於其餘Observer。當一個觸摸事件到來時,Runloop被喚醒,App中的代碼會執行一些操做,好比建立和調整視圖層級、設置UIView的frame、修改CALayer的透明度、爲視圖添加一個動畫;這些操做最終會被CALayer捕獲,並經過CATransaction提交到一箇中間狀態去。當上面的全部操做結束後,Runloop即將進入休眠(或者退出)時,關注該事件的Observer都會獲得通知。這時CA註冊的Observer就會在回調中,把全部的中間狀態合併提交到GPU去顯示;若是此處有動畫,CA會經過CADisplayLink等機制屢次觸發相關流程。

Runloop任務分發->Texture

Texture在此處模擬了Core Animation的這個機制:全部針對ASNode的修改和提交,總有些任務是必須放入主線程執行的。當出現這種任務時,ASNode會把任務用ASAsyncTransaction(Group)封裝並提交到一個全局的容器去。Texture也在Runloop中註冊了一個Observer,監視的事件和CA同樣,但優先級比CA要低。當Runloop進入休眠前、CA處理完事件後,Texture就會執行該loop內提交的全部任務。經過這種機制,Texture能夠在合適的機會把異步、併發的操做同步到主線程去,而且能得到不錯的性能。

Texture佈局引擎

相對於AutoLayout

UIKit AutoLayout 在複雜的視圖結構中,計算量會呈指數級增加,Texture的佈局方案相對AutoLayout有如下優勢:

  • 快:Texture的佈局計算和手寫frame同樣快

  • 異步和併發:佈局能夠在後臺線程上計算

  • 聲明式渲染:佈局使用不可變的數據結構聲明,實現一個layout視角從專一view之間的距離和約束,轉變成劃分和制定不一樣view子域的佈局規則,抽象層級變高,使得佈局代碼更容易開發、維護

  • 可緩存:若是佈局是不變的,自動在後臺預先計算並緩存

  • 可拓展:在不一樣的類中使用相同的佈局會變得很方便

Texture的佈局系統

Texture本身定義了一套強大的automatic layout佈局系統,這套佈局系統基於CSS的Box Model,經過提出LayoutSpec概念,使得咱們能夠經過聲明式的方法來定義佈局。

layoutTable

:一種特殊的layoutTable,與node不一樣的是,它本質只是內存中的數據結構,用以輔助view的位置計算,繪製時不須要view來佔位或者承載子元素。

佈局系統

Texture佈局規則&佈局元素

  • 佈局規則:充當LayoutElements的容器,經過多個LayoutElements之間的關聯,完成LayoutElements的位置排列,繼承自ASLayoutSpec。

  • 佈局元素:全部的ASDisplayNode和ASLayoutSpec都遵照協議,能夠經過兩個Nodes和其餘的LayoutSpecs,生成或者組合一個新的LayoutSpecs。協議及LayoutSpecs有一些屬性用於建立很是複雜的佈局。

Texture佈局流程圖

Texture佈局示例

Texture佈局調試

在任何ASDisplayNode或ASLayoutSpec上調用-asciiArtString都會返回該對象及其子項的字符圖,也能夠設置.debugName這樣也會包含在字符圖中。

還能夠在任何ASLayoutElement,好比Node和LayoutSpec上打印樣式對象,調試.size屬性。

聲明式佈局Demo連接:

https://ysw-hello@github.com/ysw-hello/TextureLayoutDemo.git

Texture所能帶來的收益

  • 異步繪製、異步渲染經過Runloop任務分發,優化複雜界面的主線程卡頓現象。

  • 圖層預合成、智能預加載的機制,對列表進行深度優化,使得體驗與性能獲得進一步的提高。

  • 聲明式佈局方式,FlexBox佈局特色,給iOS原生開發的佈局模式帶來一種新的佈局思惟,很新穎,頗有特色。

相關文章
相關標籤/搜索