本篇所涉及的性能問題我都將根據滑動的流暢性來評判, 包括掉幀狀況和一些實際體驗html
ASDK 已經更名爲 Texture, 我習慣稱做 ASDKios
編譯環境: MacOS 10.13.3, Xcode 9.2git
參與測試機型: iPhone 6 10.3.3, iPhone 7 11.2.1, iPhone X 11.2.5, 默認 iPhone 6github
TableView / TableNode 包含的 TableViewCell / CellNode: 默認複雜程度通常, 包含 1~2 張圖片和 2~4 條文本展現, 圖片有圓角segmentfault
大牛們把緣由都說的很清楚了, 致使的結果就是 16ms 不足以渲染一幀, 產生掉幀卡頓緩存
下面是嘗試過的一些優化:安全
老生長談了, 除 UITableView-FDTemplateLayoutCell 以外, QMUI 中也有提供一套緩存行高方案性能優化
具體是在 JSON 轉 Model 後把文本轉爲富文本, 處理一些弱邏輯等, 以後賦值就能夠直接展現了網絡
咳咳, 這個感受不到什麼效果併發
例如處理圖片遮罩或固定的圖標, 通常是直接使用多層視圖實現
我曾嘗試把三張小圖繪製到一張大圖上再進行展現, 因而乎, 異步複用問題除外, 內存炸了, 最終仍是老老實實用多個視圖實現
一般咱們認爲 UIKit 是不能渲染於非主線程的, 一旦你這麼作, 就可能會致使崩潰, 沒法正常顯示等問題, 而 ASDK 爲何能夠呢, 由於 ASDisplayNode 是線程安全的, Node 建立時, 不會當即在其內部新建 UIView 和 CALayer, 直到主線程第一次訪問時纔會生成對應的對象, 除此以外, 還經過圖層預合成和基於 Runloop 的異步併發, 使其擁有更好的性能 ASAsyncTransactionGroup
這個特色帶來的相關實際體驗就是: 安心的進行異步繪圖, 如圓角裁剪, 增長遮罩等, 這在 UIKit 中是足以毀滅人生的, 內存暴漲, 異步複用, 性能極差
不太低性能設備下仍是會出現明顯空白
首先來一張 Gif 體驗一下, 實際上使用 ASDK 開發完成後對比也是如此, 有種網速變快了的錯覺
ASDK 中的 ASRangeController, ASTableView, ASCollectionView 相對於 UIKit 原生控件的特色是可用於監控視圖的可見區域, 維護工做區域, 在合適的時機觸發網絡請求以及繪製, 單元格的異步佈局
這裏推薦閱讀: 預加載與智能預加載(iOS)
意思是某個 List 展現的樣式只有一種, TableView 只須要註冊一個 Cell
這種狀況下, 若是常規的一些優化得當, 滾動的流暢性仍是能夠接受的(與 ASDK 差距微小, 但仍然肉眼可分辨)
此時的差距主要體如今列表某項數據第一次展現, 以及 TableView 在分頁加載時產生的等待較長, 固然, 這兩點也是能夠繼續優化和解決的
相反的, 也就是來回滑動已經展現過的數據, 二者的差距就很是小了, 大概是 59.7 - 59.9 和 59.9 的區別 (我瞎扯的)
綜上, 優化得當的狀況下, 單一的 Cell 狀況下 UIKit 與 ASDK 的差距不明顯
表示某 List 中有多種不一樣的樣式, TableView 必需要經過註冊 N 個 Cell 來實現
這種狀況下, 假設有 5 種 Cell, 屏幕可同時展現 6 條 Cell, 此時若第一屏幕恰好展現的就包含所有 5 種 Cell , 那麼後續的滑動狀況將與單一的 Cell表現一致, 若第一屏幕展現的內容只包含一種, 其餘 4 種沒有在屏幕上出現過, 那麼當某一種首次出如今屏幕上時, 便會出現明顯的卡頓; 我嘗試過解決這個問題, 提早建立全部的 Cell 實例對象, 緩存和複用相同的子視圖, 異步預繪製爲一張圖片並緩存(坑), 都收效漸微
因 ASDK 支持預渲染, 與處理單種 Cell 沒有區別, 依舊 59.9
TableView 的複用機制我是既愛又恨的, 方便之處在於直接與數據綁定後, 能夠方便的更新和修改, 只需保證 setModel 簡潔就 OK, 只是當業務綁定較多時就比較麻煩了
下面重點說說 TableNode, TableNode 的複用機制就是沒有複用, 只有緩存, 每一個 CellNode 都是全新的, 所以會有一些特殊的地方:
CellNode 與數據源沒有綁定關係: 建立後就算把數據源刪除, TableNode 依然能夠正常展現
數據直接決定要建立一個怎樣的 CellNode: 這一點很重要, TableViewCell 的展現大體爲: 添加空假數據子視圖 -> 數據填充 -> 刷新, 涉及佈局或圖文時會更復雜
CellNode 只有一步: 添加真數據的子視圖; 所以能夠直接根據業務邏輯對控件和佈局作出處理, 而不用一次或屢次刷新
Demo: 此處需求爲每組一個大圖 + N個小圖, 每組 3 或 5 個
解決思路: TableView 的方式是建立 5 個, 根據數量顯隱下面兩個, 或者兩種 Cell, 把 3 和 5 的狀況分別對應, 除此以外, 最重要的是: 祈禱數據正常, 每組數據個數僅爲 3 或 5
此時若使用 TableNode 就靈活多了, 能夠根據須要(數據個數), 加入須要的子視圖, 個人思路是把頂部的大圖固定, 剩下的兩個爲一行進行添加, 就算總數爲偶數也是沒有任何額外消耗的, 具體參見 ASDKDemo
ASDK 使用的是 Flex 佈局, 且面向對象
偷一張圖
具體對比: iOS 上的 FlexBox 佈局
簡單來講, 缺點只有一個, 就是學習曲線相對 Frame AutoLayout 更陡峭, 而優勢是 性能與 Frame 至關, 上手後比 AutoLayout 還簡單, 若是你已經開始嘗試, 請堅持下去
使用 AutoLayout 時我內心想的無外乎:
缺點是視圖之間的依賴性太強, 可讀性維護性較差(更差的是 Frame), 例如排列數個距離不等控件, 就會很厭煩, 而後 cv 重複代碼; 處理多個多行文本垂直排列時很噁心, 想要處理好最終須要去計算文字行高, 外加入自定行間距; ...
例如 Demo 中的
<img src="https://img.didee.cn/imgs/201...; width="300"/>
我作的事情是:
postImageRatioSpec
titleInsetSpec
titleInsetSpec
的位置是垂直方向下的最尾部; titleRelativeSpec
titleRelativeSpec
是覆蓋到 postImageRatioSpec
上: titleOverlaySpec
此時大圖和文字佈局完成
接下來是用戶欄:
leftStackSpec
rightStackSpec
leftStackSpec
和 rightStackSpec
水平排列, 等間距排列填充(實際是爲 left 和 rightStack 進行填充), 距離 8, 對齊方式填充(無實際做用, 因爲子視圖同爲 Stack 且都是水平方向); userStackSpec
最後:
titleOverlaySpec
和 userStackSpec
垂直排列, 自上而下, 對齊方式填充(同理於userStackSpec
, 此處影響的是 userStackSpec
); videoStackSpec
videoStackSpec
的內邊距: Inset(16, 16, 0, 16); videoInsetSpec
特別注意 userStackSpec
和 videoStackSpec
, StackSpec 多層疊加後, 父子間是存在影響的, 我在使用中也感受比較奇怪, 具體須要自行嘗試體會..
具體實現代碼: VideoCellNode.m , UserNode.m
AsyncDisplayKit 系列教程 —— 爲何要使用 AsyncDisplayKit
AsyncDisplayKit State of the Code (WWDC 2016)
包含無限滾動和不定子視圖的 Demo ASDKDemo
官方示例 Texture Examples
線上項目 AppStore 耐飛視頻