Pluto - iOS 上一個高性能的排版渲染引擎

做者:Wison,騰訊移動客戶端開發 高級工程師
商業轉載請聯繫騰訊WeTest得到受權,非商業轉載請註明出處。
原文連接:http://wetest.qq.com/lab/view/369.htmlhtml

WeTest 導讀

Pluto 是 iOS 上的一個排版渲染引擎,經過 JSON/JS 文件能夠很方便地描述界面元素,開發效率很高,而且在流暢度,內存等方便有保證。ios


Qzone Feed 業務複雜,樣式不少。每次新增一種 Feed 樣式,開發工做量很大,須要跟版本。樣式之間耦合嚴重,每改一種樣式,另外一種樣式可能會受影響。
圖片描述json

基於這樣的背景下,Feed Team 急需一個比較成熟的渲染引擎,他至少須要解決如下問題緩存

一、提高開發效率。安全

二、樣式之間獨立,不互相耦合。性能優化

三、新增和修改 Feed 樣式不須要跟版本。框架

四、不管採起什麼方案,列表的滑動流暢度必需保證至少跟現有的同樣。異步

基於這樣的需求,咱們從新盤點了市面上比較成熟的排版渲染引擎 ComponentKit,新的開發框架好比 React Native,甚至參考 Android 的排版系統。都難以同時解決上述問題,最終決定咱們本身來作一個,一個專一性能和開發效率的排版引擎,Pluto。目前 Pluto 已經應用於 QQ,Qzone 上大部分的空間 Feed 樣式,關於 Pluto 和這些現有的排版渲染引擎對比的細節,我後面會說明,咱們先來看看 Pluto 用起來是怎麼樣的。工具

首先須要一個排版描述:性能

圖片描述

以上排版數據的結果以下,左邊是一個圖片控件,右邊是文字控件。

圖片描述

想必看到這個 demo,你們應該知道 Pluto 是什麼東西了。上面的 JSON 文件閱讀起來也很是天然,直接。接下來要解決的問題比較多。這裏重點描述點擊事件、模板、重用、擴展。分別解決熱更新,開發效率,性能優化、功能擴充,四個方面的問題。

點擊事件

Pluto 還能夠經過 json 描述綁定事件響應的 js 腳本,好比如下 json 文件:
圖片描述

圖片組件被點擊的時候,能夠找到相應的 js 文件,調用 onClick 方法。

模版

一開始的例子中,使用一個 JSON 表達了一個 UI 排版,假若有不少相似的界面元素同時存在,就有不少重複數據的 JSON 文件。這個時候就須要模版特性。好比列表中的每一個 Cell,都共享同一個模版,只是填充的數據不同。如下例子中,將 "imageName" 替換成"${image}",而不是一個具體的圖片。而後提供一個字典映射,每個數據項映射不一樣的數據,產生不一樣的視圖。

圖片描述

圖片描述

圖片描述

重用

重用是 Pluto 在設計之初就比較重點考慮的一個因素,也是不一樣於其餘引擎的最大的特點。能夠說有了這個特性,才能應用在列表等有高性能要求的場景。重用指的是,在 UITableView 等列表控件,在滑動的時候,不一樣列表項複用同一個 Cell,Cell 裏面的視圖數據能夠重複使用,核心是爲了減小建立視圖和修改視圖樹的次數。值得強調的是,Pluto 裏面對視圖的重用優化,是已經內置的功能,調用方不須要額外操做。

實現原理以下圖所示,每一個 Pluto 生成的視圖中,會包含一個複用池,當使用複用特性時,視圖不會被銷燬,而是被回收,回收時,其子視圖會被放入複用池內,(這裏的子視圖是一個視圖樹,即也包含了子視圖的子視圖)並隱藏起來。複用時,就只需恢復顯示,調整寬高,數據等,比建立視圖的成本低不少。

圖片描述

擴展

Pluto 內置了一些渲染控件,好比 文字(TextItem),圖片(ImageItem),按鈕(ButtonItem)。若是這些組件不知足需求,還能夠經過擴展組件來完成封裝。實現自定義控件的大概流程以下:

圖片描述

在 demo 裏面有演示,包含了實現一個自定義視圖的更多細節。

特色分析

這裏梳理一下 Pluto 的一些特色。

快速:Pluto 的排版性能與直接書寫的排版代碼性能相差不大。目前在手機 QQ 上跟其餘列表相比,流暢度領先。(固然,比 Auto Layout 性能好不少)

異步:Pluto 的整個排版,文字渲染流程,都是能夠在工做線程執行的,而且線程安全。不會影響用戶操做。

描述型排版:Pluto 接收的排版信息是一個字典,描述型的表達排版信息,不須要寫邏輯代碼。作成描述型的好處是:

● 方便維護,不易出錯(由於不包含代碼)。

● 方便緩存。

● 能夠是寫成 JSON 格式,經過本地讀取,或者後臺下發來排版。

● 不可變數據: 在整個排版引擎中,排版數據是不可變的,這意味着很容易維護、測試、緩存、複用以及作到線程安全等等。

緩存和複用:因爲排版數據是不可變的,因此內部會進行緩存,這樣能夠加快整個顯示流程。渲染部分則會盡可能複用已存在的控件,加快渲染。同時同一個視圖的排版數據更新,也會內部作差別化對比,排版流程中也會盡量地複用舊的排版信息。

模版體系:Pluto 有完整的模版功能。一樣的樣式只須要書寫一次,造成模版,而後根據狀況往模版填充不一樣的數據,能夠生成不一樣的視圖。模版之間也能夠經過組合來複用。

圖文混排:Pluto 支持基礎控件的混排,好比 Text 標籤,Image 標籤,也支持自定義標籤和自定義控件。

對比分析

在對比分析以前,咱們先 review 一下 Pluto 的使用主場景:一個能夠無限加載更多 Feed 的 Feed 列表,要求內存,CPU,流暢度都有不錯的表現。

針對這個場景,對比分析現有主流的界面開發庫,分別是 Xcode 自帶的 Storyboard/Xib,Facebook 主導的開源組件 ReactNative、ComponentKit,以及本文的 Pluto。

● storyboard 是一個可視化的 UI 編輯工具,開發效率比較高。性能上,控件都使用了原生控件,因此性能會差一些。也不支持異步排版,影響流暢度。生成的文件是使用 XML 描述,理論上是能夠動態下發,可是 XML 格式不公開,各個版本也不保證兼容,因此比較難作到動態下發。

● React Native 使用 JS+HTML 的方式進行開發,開發效率很高。也有很高的動態性和跨平臺特性。可是性能比較捉急,在速度上,內存使用上有一些問題,很難在 Feed 流這種性能要求比較高的地方。

● ComponentKit 跟 Pluto 其實很相似,區別最大的地方在於 Component 不支持 JSON/XML 這種靜態表達樣式的功能,以及事件動態綁定的功能。在動態性和可維護性方面,會弱不少。咱們有思考過在 ComponentKit 的基礎上增長 JSON 表達樣式的功能。可是

ComponentKit 直接使用了原生視圖,並無一箇中間的虛擬視圖層,因此性能上也是問題。改形成本過高。

● Pluto 相比 React Native 來講,組件不夠豐富,使用 JSON 可讓開發效率在描述排版方面接近 React

Native;性能相比其餘組件來講很不錯;支持異步保證了主線程的流暢度;動態性跟 React Native 同樣,不能新增控件,控件都是本地預埋。比較依賴本地代碼的邏輯,不能修改本地代碼的已有邏輯,可是能夠替換一部分。固然,邏輯只能預埋的話,也不會有審覈風險。

梳理表格以下:

圖片描述

騰訊WeTest iOS預審工具

爲了提升IEG蘋果審覈經過率,騰訊專門成立了蘋果審覈測試團隊,打造出iOS預審工具這款產品。通過1年半的內部運營,騰訊內部應用的iOS審覈經過率從平均35%提高到90%+。

現將騰訊內部產品的過審經驗,以線上工具的形式共享給各位。在WeTest騰訊質量開放平臺上能夠在線使用。點擊 http://wetest.qq.com/product/ios 便可當即體驗!

若是使用當中有任何疑問,歡迎聯繫騰訊WeTest企業QQ:800024531

相關文章
相關標籤/搜索