1. 程式人生 > >AsyncDisplayKit原始碼解析-整體(一)

AsyncDisplayKit原始碼解析-整體(一)

前言

本文的中文註釋程式碼demo更新在我的github上。

AsyncDisplayKit 是 Facebook 開源的一個用於保持 iOS 介面流暢的框架。主要作者是 Scott Goodson(github)。
本文主要是從理論和原始碼角度分析一下整個ASDK庫,其中參考了很多參考資料中的內容,加以整理和複習。

發展歷史

AsyncDisplayKit(ASDK)是2012年由Facebook開始著手開發,並於2014年出品的高效能顯示類庫,主要作者是Scott Goodson。Scott曾經參與了多個iOS版本系統的開發,包括UIKit以及一些系統原生app,後來加入Facebook並參與了ASDK的開發並應用到Paper,因此該庫有機會從相對底層的角度來進行一系列的優化。

解決的問題

很多時候使用者在操作app的時候,會感覺到不適那麼流暢,有所卡頓。
ASDK主要就是解決的問題就是操作頁面過程中的保持幀率在60fps(理想狀態下)的問題。

造成卡頓的原因有很多,總結一句話基本上就是:
CPU或GPU消耗過大,導致在一次同步訊號之間沒有準備完成,沒有內容提交,導致掉幀的問題。

具體的原理,在提升 iOS 介面的渲染效能文章中介紹的十分詳細了,這裡也不多闡述了。

優化原理

從ASDK的視訊與tutorial上,可以整理出三個ASDK主要優化的方面:
1. 佈局
iOS自帶的Autolayout在佈局效能上存在瓶頸,並且只能在主執行緒進行計算。(參考

Auto Layout Performance on iOS)因此ASDK棄用了Autolayout,自己參考自家的ComponentKit設計了一套佈局方式。
2. 渲染
對於大量文字,圖片等的渲染,UIKit元件只能在主執行緒並且可能會造成GPU繪製的資源緊張。ASDK使用了一些方法,比如圖層的預混合等,並且非同步的在後臺繪製圖層,不阻塞主執行緒的執行。
3. 系統物件創建於銷燬
UIKit元件封裝了CALayer圖層的物件,在建立、調整、銷燬的時候,都會在主執行緒消耗資源。ASDK自己設計了一套Node機制,也能夠呼叫。

**實際上,從上面的一些解釋也可以看出,ASDK最大的特點就是”非同步”。
將消耗時間的渲染、圖片解碼、佈局以及其它 UI 操作等等全部移出主執行緒,這樣主執行緒就可以對使用者的操作及時做出反應,來達到流暢執行的目的。
**

ASDisplayNode的整體設計

AsyncDisplayKit’s basic unit is the node. ASDisplayNode is an abstraction over UIView, which in turn is an abstraction over CALayer. Unlike views, which can only be used on the main thread, nodes are thread-safe: you can instantiate and configure entire hierarchies of them in parallel on background threads.

這段是ASDK官網上的原話。可以看出ASDK的核心就是ASDisplayNode。在介紹ASDisplayNode前,需要介紹一下目前UIView於CALayer的關係。

UIView與CALayer的關係:

UIView持有CALayer,顯示依靠CALayer。
CALayer的delegate是UIView,可以回撥通知UIView的變化。
UIView 和 CALayer 都不是執行緒安全的,並且只能在主執行緒建立、訪問和銷燬。
UIKit

ASDisplayNode

ASNode(ASDisplayNode以下同)仿照這樣的關係,通過view去持有UIView,並且讓UIView通過.node回撥自己。在ASNode中封裝了常見的檢視屬性,讓開發者直接去呼叫ASNode進行開發。
ASNode

並且ASNode可以設定layer backed屬性,就是不需要響應觸控事件。這時候ASNode將直接操作CALayer進行顯示,更加優化了效能。
Paste_Image.png

ASNode本身是執行緒安全的,所以它允許在後臺執行緒進行建立和修改。

Node 剛建立時,並不會在內部新建 UIView 和 CALayer,直到第一次在主執行緒訪問 view 或 layer 屬性時,它才會在內部生成對應的物件。當它的屬性(比如frame/transform)改變後,它並不會立刻同步到其持有的 view 或 layer 去,而是把被改變的屬性儲存到內部的一箇中間變數,稍後在需要時,再通過某個機制一次性設定到內部的 view 或 layer。

ASDK整體提供了十分多的Node元件,比如Button,Cell等等,利用這些元件,開發者可以繞過UIKit進行開發。這裡貼一張官網上的層級圖
node層級

渲染過程

ASDisplayNode的渲染過程主要有以下幾步:

  1. 初始化ASDisplayNode對應的 UIView 或者 CALayer
  2. 在當前檢視進入檢視層級時執行 setNeedsDisplay;
  3. display 方法執行時,向後臺執行緒派發繪製事務;
  4. 在Runloop中註冊observer,在每個 RunLoop 結束時回撥。

這邊的細化會在之後介紹原始碼的時候介紹。

其他內容

ASDK還包含以下內容:

  • ASLayout的佈局功能
  • ASAsyncTransaction的非同步繪製控制
  • ASViewController結點容器
  • ASTableView/ASCollectionView以及對應的控制器ASRangeController/ASDataController

總結

本文大體上介紹了一下AsyncDisplayKit的整體流程和優化方法,之後的幾章將從原始碼角度去分析ASDK的渲染過程。

參考資料