Pluto - iOS 上一个高性能的排版渲染引擎
Pluto 是 iOS 上的一個(gè)排版渲染引擎,通過(guò) JSON/JS 文件可以很方便地描述界面元素,開(kāi)發(fā)效率很高,并且在流暢度,內(nèi)存等方便有保證。pluto.oa.com 上有更多詳細(xì)資料。
Qzone Feed 業(yè)務(wù)復(fù)雜,樣式很多。每次新增一種 Feed 樣式,開(kāi)發(fā)工作量很大,需要跟版本。樣式之間耦合嚴(yán)重,每改一種樣式,另一種樣式可能會(huì)受影響。
?
基于這樣的背景下,Feed Team 急需一個(gè)比較成熟的渲染引擎,他至少需要解決以下問(wèn)題:
1、提升開(kāi)發(fā)效率。
2、樣式之間獨(dú)立,不互相耦合。
3、新增和修改 Feed 樣式不需要跟版本。
4、無(wú)論采取什么方案,列表的滑動(dòng)流暢度必需保證至少跟現(xiàn)有的一樣。
基于這樣的需求,我們重新盤(pán)點(diǎn)了市面上比較成熟的排版渲染引擎 ComponentKit,新的開(kāi)發(fā)框架比如 React Native,甚至參考 Android 的排版系統(tǒng)。都難以同時(shí)解決上述問(wèn)題,最終決定我們自己來(lái)做一個(gè),一個(gè)專(zhuān)注性能和開(kāi)發(fā)效率的排版引擎,Pluto。目前 Pluto 已經(jīng)應(yīng)用于 QQ,Qzone 上大部分的空間 Feed 樣式,關(guān)于 Pluto 和這些現(xiàn)有的排版渲染引擎對(duì)比的細(xì)節(jié),我后面會(huì)說(shuō)明,我們先來(lái)看看 Pluto 用起來(lái)是怎么樣的。
首先需要一個(gè)排版描述:
?
以上排版數(shù)據(jù)的結(jié)果如下,左邊是一個(gè)圖片控件,右邊是文字控件。
?
想必看到這個(gè) demo,大家應(yīng)該知道 Pluto 是什么東西了。上面的 JSON 文件閱讀起來(lái)也非常自然,直接。接下來(lái)要解決的問(wèn)題比較多。這里重點(diǎn)描述點(diǎn)擊事件、模板、重用、擴(kuò)展。分別解決熱更新,開(kāi)發(fā)效率,性能優(yōu)化、功能擴(kuò)充,四個(gè)方面的問(wèn)題。
點(diǎn)擊事件
Pluto 還可以通過(guò) json 描述綁定事件響應(yīng)的 js 腳本,比如以下 json 文件:
?
圖片組件被點(diǎn)擊的時(shí)候,可以找到相應(yīng)的 js 文件,調(diào)用 onClick 方法。
模版
一開(kāi)始的例子中,使用一個(gè) JSON 表達(dá)了一個(gè) UI 排版,假如有很多類(lèi)似的界面元素同時(shí)存在,就有很多重復(fù)數(shù)據(jù)的 JSON 文件。這個(gè)時(shí)候就需要模版特性。比如列表中的每個(gè) Cell,都共享同一個(gè)模版,只是填充的數(shù)據(jù)不一樣。以下例子中,將 "imageName" 替換成"${image}",而不是一個(gè)具體的圖片。然后提供一個(gè)字典映射,每一個(gè)數(shù)據(jù)項(xiàng)映射不同的數(shù)據(jù),產(chǎn)生不同的視圖。
?
重用
重用是 Pluto 在設(shè)計(jì)之初就比較重點(diǎn)考慮的一個(gè)因素,也是不同于其他引擎的最大的特色。可以說(shuō)有了這個(gè)特性,才能應(yīng)用在列表等有高性能要求的場(chǎng)景。重用指的是,在 UITableView 等列表控件,在滑動(dòng)的時(shí)候,不同列表項(xiàng)復(fù)用同一個(gè) Cell,Cell 里面的視圖數(shù)據(jù)可以重復(fù)使用,核心是為了減少創(chuàng)建視圖和修改視圖樹(shù)的次數(shù)。值得強(qiáng)調(diào)的是,Pluto 里面對(duì)視圖的重用優(yōu)化,是已經(jīng)內(nèi)置的功能,調(diào)用方不需要額外操作。
實(shí)現(xiàn)原理如下圖所示,每個(gè) Pluto 生成的視圖中,會(huì)包含一個(gè)復(fù)用池,當(dāng)使用復(fù)用特性時(shí),視圖不會(huì)被銷(xiāo)毀,而是被回收,回收時(shí),其子視圖會(huì)被放入復(fù)用池內(nèi),(這里的子視圖是一個(gè)視圖樹(shù),即也包含了子視圖的子視圖)并隱藏起來(lái)。復(fù)用時(shí),就只需恢復(fù)顯示,調(diào)整寬高,數(shù)據(jù)等,比創(chuàng)建視圖的成本低很多。
?
擴(kuò)展
Pluto 內(nèi)置了一些渲染控件,比如 文字(TextItem),圖片(ImageItem),按鈕(ButtonItem)。如果這些組件不滿(mǎn)足需求,還可以通過(guò)擴(kuò)展組件來(lái)完成封裝。實(shí)現(xiàn)自定義控件的大概流程如下:
?
在 demo 里面有演示,包含了實(shí)現(xiàn)一個(gè)自定義視圖的更多細(xì)節(jié)。
特點(diǎn)分析
這里梳理一下 Pluto 的一些特點(diǎn)。
快速:Pluto 的排版性能與直接書(shū)寫(xiě)的排版代碼性能相差不大。目前在手機(jī) QQ 上跟其他列表相比,流暢度領(lǐng)先。(當(dāng)然,比 Auto Layout 性能好很多)異步:Pluto 的整個(gè)排版,文字渲染流程,都是可以在工作線(xiàn)程執(zhí)行的,并且線(xiàn)程安全。不會(huì)影響用戶(hù)操作。
描述型排版:Pluto 接收的排版信息是一個(gè)字典,二手手機(jī)號(hào)碼買(mǎi)賣(mài)平臺(tái)描述型的表達(dá)排版信息,不需要寫(xiě)邏輯代碼。做成描述型的好處是:
● 方便維護(hù),不易出錯(cuò)(因?yàn)椴话a)。
● 方便緩存。
● 可以是寫(xiě)成 JSON 格式,通過(guò)本地讀取,或者后臺(tái)下發(fā)來(lái)排版。
● 不可變數(shù)據(jù): 在整個(gè)排版引擎中,排版數(shù)據(jù)是不可變的,這意味著很容易維護(hù)、測(cè)試、緩存、復(fù)用以及做到線(xiàn)程安全等等。
緩存和復(fù)用:由于排版數(shù)據(jù)是不可變的,所以?xún)?nèi)部會(huì)進(jìn)行緩存,這樣可以加快整個(gè)顯示流程。渲染部分則會(huì)盡量復(fù)用已存在的控件,加快渲染。同時(shí)同一個(gè)視圖的排版數(shù)據(jù)更新,也會(huì)內(nèi)部做差異化對(duì)比,排版流程中也會(huì)盡可能地復(fù)用舊的排版信息。
模版體系:Pluto 有完整的模版功能。同樣的樣式只需要書(shū)寫(xiě)一次,形成模版,然后根據(jù)情況往模版填充不同的數(shù)據(jù),可以生成不同的視圖。模版之間也可以通過(guò)組合來(lái)復(fù)用。
圖文混排:Pluto 支持基礎(chǔ)控件的混排,比如 Text 標(biāo)簽,Image 標(biāo)簽,也支持自定義標(biāo)簽和自定義控件。
對(duì)比分析
在對(duì)比分析之前,我們先 review 一下 Pluto 的使用主場(chǎng)景:一個(gè)可以無(wú)限加載更多 Feed 的 Feed 列表,要求內(nèi)存,CPU,流暢度都有不錯(cuò)的表現(xiàn)。
針對(duì)這個(gè)場(chǎng)景,對(duì)比分析現(xiàn)有主流的界面開(kāi)發(fā)庫(kù),分別是 Xcode 自帶的 Storyboard/Xib,Facebook 主導(dǎo)的開(kāi)源組件 ReactNative、ComponentKit,以及本文的 Pluto。
● storyboard 是一個(gè)可視化的 UI 編輯工具,開(kāi)發(fā)效率比較高。性能上,控件都使用了原生控件,所以性能會(huì)差一些。也不支持異步排版,影響流暢度。生成的文件是使用 XML 描述,理論上是可以動(dòng)態(tài)下發(fā),但是 XML 格式不公開(kāi),各個(gè)版本也不保證兼容,所以比較難做到動(dòng)態(tài)下發(fā)。
● React Native 使用 JS+HTML 的方式進(jìn)行開(kāi)發(fā),開(kāi)發(fā)效率很高。也有很高的動(dòng)態(tài)性和跨平臺(tái)特性。但是性能比較捉急,在速度上,內(nèi)存使用上有一些問(wèn)題,很難在 Feed 流這種性能要求比較高的地方。
● ComponentKit 跟 Pluto 其實(shí)很類(lèi)似,區(qū)別最大的地方在于 Component 不支持 JSON/XML 這種靜態(tài)表達(dá)樣式的功能,以及事件動(dòng)態(tài)綁定的功能。在動(dòng)態(tài)性和可維護(hù)性方面,會(huì)弱很多。我們有思考過(guò)在 ComponentKit 的基礎(chǔ)上增加 JSON 表達(dá)樣式的功能。但是 ComponentKit 直接使用了原生視圖,并沒(méi)有一個(gè)中間的虛擬視圖層,所以性能上也是問(wèn)題。改造成本太高。
● Pluto 相比 React Native 來(lái)說(shuō),組件不夠豐富,使用 JSON 可以讓開(kāi)發(fā)效率在描述排版方面接近 React Native;性能相比其他組件來(lái)說(shuō)很不錯(cuò);支持異步保證了主線(xiàn)程的流暢度;動(dòng)態(tài)性跟 React Native 一樣,不能新增控件,控件都是本地預(yù)埋。比較依賴(lài)本地代碼的邏輯,不能修改本地代碼的已有邏輯,但是可以替換一部分。當(dāng)然,邏輯只能預(yù)埋的話(huà),也不會(huì)有審核風(fēng)險(xiǎn)。
梳理表格如下:
via:
總結(jié)
以上是生活随笔為你收集整理的Pluto - iOS 上一个高性能的排版渲染引擎的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 真良心大厂EPIC,页游广告又有新素材了
- 下一篇: 如何做好游戏内实时语音体验