<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## **AsyncDisplayKit** AsyncDisplayKit 是 Facebook 開源的一個用于保持 iOS 界面流暢的庫,我從中學到了很多東西,所以下面我會花較大的篇幅來對其進行介紹和分析。 [TOC=3,3] ### **ASDK 的由來** ![](https://box.kancloud.cn/2015-11-19_564d50036b436.png) ASDK 的作者是 Scott Goodson ([Linkedin](https://www.linkedin.com/in/iosengineer)), 他曾經在蘋果工作,負責 iOS 的一些內置應用的開發,比如股票、計算器、地圖、鐘表、設置、Safari 等,當然他也參與了 UIKit framework 的開發。后來他加入 Facebook 后,負責 Paper 的開發,創建并開源了 AsyncDisplayKit。目前他在 Pinterest 和 Instagram 負責 iOS 開發和用戶體驗的提升等工作。 ![](https://box.kancloud.cn/2015-11-19_564d50038af1e.png) ASDK 自 2014 年 6 月開源,10 月發布 1.0 版。目前 ASDK 即將要發布 2.0 版。 V2.0 增加了更多布局相關的代碼,ComponentKit 團隊為此貢獻很多。 現在 Github 的 master 分支上的版本是 V1.9.1,已經包含了 V2.0 的全部內容。 ### **ASDK 的資料** 想要了解 ASDK 的原理和細節,最好從下面幾個視頻開始: 2014.10.15?[NSLondon - Scott Goodson - Behind AsyncDisplayKit](https://www.youtube.com/watch?v=-IPMNWqA638) 2015.03.02?[MCE 2015 - Scott Goodson - Effortless Responsiveness with AsyncDisplayKit](https://www.youtube.com/watch?v=ZPL4Nse76oY) 2015.10.25?[AsyncDisplayKit 2.0: Intelligent User Interfaces - NSSpain 2015](https://www.youtube.com/watch?v=RY_X7l1g79Q) 前兩個視頻內容大同小異,都是介紹 ASDK 的基本原理,附帶介紹 POP 等其他項目。 后一個視頻增加了 ASDK 2.0 的新特性的介紹。 除此之外,還可以到 Github Issues 里看一下 ASDK 相關的討論,下面是幾個比較重要的內容: [關于 Runloop Dispatch](https://github.com/facebook/AsyncDisplayKit/issues/42) [關于 ComponentKit 和 ASDK 的區別](https://github.com/facebook/AsyncDisplayKit/issues/70) [為什么不支持 Storyboard 和 Autolayout](https://github.com/facebook/AsyncDisplayKit/issues/132) [如何評測界面的流暢度](https://github.com/facebook/AsyncDisplayKit/issues/204) 之后,還可以到 Google Groups 來查看和討論更多內容: [https://groups.google.com/forum/#!forum/asyncdisplaykit](https://groups.google.com/forum/#!forum/asyncdisplaykit) ### **ASDK 的基本原理** ![](https://box.kancloud.cn/2015-11-19_564d50039d05c.png) ASDK 認為,阻塞主線程的任務,主要分為上面這三大類。文本和布局的計算、渲染、解碼、繪制都可以通過各種方式異步執行,但 UIKit 和 Core Animation 相關操作必需在主線程進行。ASDK 的目標,就是盡量把這些任務從主線程挪走,而挪不走的,就盡量優化性能。 為了達成這一目標,ASDK 嘗試對 UIKit 組件進行封裝: ![](https://box.kancloud.cn/2015-11-19_564d5003b06b2.png) 這是常見的 UIView 和 CALayer 的關系:View 持有 Layer 用于顯示,View 中大部分顯示屬性實際是從 Layer 映射而來;Layer 的 delegate 在這里是 View,當其屬性改變、動畫產生時,View 能夠得到通知。UIView 和 CALayer 不是線程安全的,并且只能在主線程創建、訪問和銷毀。 ![](https://box.kancloud.cn/2015-11-19_564d5003c469c.png) ASDK 為此創建了 ASDisplayNode 類,包裝了常見的視圖屬性(比如 frame/bounds/alpha/transform/backgroundColor/superNode/subNodes 等),然后它用 UIView->CALayer 相同的方式,實現了 ASNode->UIView 這樣一個關系。 ![](https://box.kancloud.cn/2015-11-19_564d5003d8c06.png) 當不需要響應觸摸事件時,ASDisplayNode 可以被設置為 layer backed,即 ASDisplayNode 充當了原來 UIView 的功能,節省了更多資源。 與 UIView 和 CALayer 不同,ASDisplayNode 是線程安全的,它可以在后臺線程創建和修改。Node 剛創建時,并不會在內部新建 UIView 和 CALayer,直到第一次在主線程訪問 view 或 layer 屬性時,它才會在內部生成對應的對象。當它的屬性(比如frame/transform)改變后,它并不會立刻同步到其持有的 view 或 layer 去,而是把被改變的屬性保存到內部的一個中間變量,稍后在需要時,再通過某個機制一次性設置到內部的 view 或 layer。 通過模擬和封裝 UIView/CALayer,開發者可以把代碼中的 UIView 替換為 ASNode,很大的降低了開發和學習成本,同時能獲得 ASDK 底層大量的性能優化。為了方便使用, ASDK 把大量常用控件都封裝成了 ASNode 的子類,比如 Button、Control、Cell、Image、ImageView、Text、TableView、CollectionView 等。利用這些控件,開發者可以盡量避免直接使用 UIKit 相關控件,以獲得更完整的性能提升。 ### **ASDK 的圖層預合成** ![](https://box.kancloud.cn/2015-11-19_564d5003f231d.png)? ![](https://box.kancloud.cn/2015-11-19_564d500427560.png) 有時一個 layer 會包含很多 sub-layer,而這些 sub-layer 并不需要響應觸摸事件,也不需要進行動畫和位置調整。ASDK 為此實現了一個被稱為 pre-composing 的技術,可以把這些 sub-layer 合成渲染為一張圖片。開發時,ASNode 已經替代了 UIView 和 CALayer;直接使用各種 Node 控件并設置為 layer backed 后,ASNode 甚至可以通過預合成來避免創建內部的 UIView 和 CALayer。 通過這種方式,把一個大的層級,通過一個大的繪制方法繪制到一張圖上,性能會獲得很大提升。CPU 避免了創建 UIKit 對象的資源消耗,GPU 避免了多張 texture 合成和渲染的消耗,更少的 bitmap 也意味著更少的內存占用。 ### **ASDK 異步并發操作** ![](https://box.kancloud.cn/2015-11-19_564d50045187c.png) 自 iPhone 4S 起,iDevice 已經都是雙核 CPU 了,現在的 iPad 甚至已經更新到 3 核了。充分利用多核的優勢、并發執行任務對保持界面流暢有很大作用。ASDK 把布局計算、文本排版、圖片/文本/圖形渲染等操作都封裝成較小的任務,并利用 GCD 異步并發執行。如果開發者使用了 ASNode 相關的控件,那么這些并發操作會自動在后臺進行,無需進行過多配置。 ### **Runloop 任務分發** Runloop work distribution 是 ASDK 比較核心的一個技術,ASDK 的介紹視頻和文檔中都沒有詳細展開介紹,所以這里我會多做一些分析。如果你對 Runloop 還不太了解,可以看一下我之前的文章[?深入理解RunLoop](http://blog.ibireme.com/2015/05/18/runloop/),里面對 ASDK 也有所提及。 ![](https://box.kancloud.cn/2015-11-19_564d50048e0fb.png) iOS 的顯示系統是由 VSync 信號驅動的,VSync 信號由硬件時鐘生成,每秒鐘發出 60 次(這個值取決設備硬件,比如 iPhone 真機上通常是 59.97)。iOS 圖形服務接收到 VSync 信號后,會通過 IPC 通知到 App 內。App 的 Runloop 在啟動后會注冊對應的 CFRunLoopSource 通過 mach_port 接收傳過來的時鐘信號通知,隨后 Source 的回調會驅動整個 App 的動畫與顯示。 Core Animation 在 RunLoop 中注冊了一個 Observer,監聽了 BeforeWaiting 和 Exit 事件。這個 Observer 的優先級是 2000000,低于常見的其他 Observer。當一個觸摸事件到來時,RunLoop 被喚醒,App 中的代碼會執行一些操作,比如創建和調整視圖層級、設置 UIView 的 frame、修改 CALayer 的透明度、為視圖添加一個動畫;這些操作最終都會被 CALayer 捕獲,并通過 CATransaction 提交到一個中間狀態去(CATransaction 的文檔略有提到這些內容,但并不完整)。當上面所有操作結束后,RunLoop 即將進入休眠(或者退出)時,關注該事件的 Observer 都會得到通知。這時 CA 注冊的那個 Observer 就會在回調中,把所有的中間狀態合并提交到 GPU 去顯示;如果此處有動畫,CA 會通過 DisplayLink 等機制多次觸發相關流程。 ASDK 在此處模擬了 Core Animation 的這個機制:所有針對 ASNode 的修改和提交,總有些任務是必需放入主線程執行的。當出現這種任務時,ASNode 會把任務用 ASAsyncTransaction(Group) 封裝并提交到一個全局的容器去。ASDK 也在 RunLoop 中注冊了一個 Observer,監視的事件和 CA 一樣,但優先級比 CA 要低。當 RunLoop 進入休眠前、CA 處理完事件后,ASDK 就會執行該 loop 內提交的所有任務。具體代碼見這個文件:[ASAsyncTransactionGroup](https://github.com/facebook/AsyncDisplayKit/blob/master/AsyncDisplayKit%2FDetails%2FTransactions%2F_ASAsyncTransactionGroup.m)。 通過這種機制,ASDK 可以在合適的機會把異步、并發的操作同步到主線程去,并且能獲得不錯的性能。 ### **其他** ASDK 中還有封裝很多高級的功能,比如滑動列表的預加載、V2.0添加的新的布局模式等。ASDK 是一個很龐大的庫,它本身并不推薦你把整個 App 全部都改為 ASDK 驅動,把最需要提升交互性能的地方用 ASDK 進行優化就足夠了。
                  <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>

                              哎呀哎呀视频在线观看