大屏小程序探索實(shí)踐 | Cube 技術(shù)解讀
?????♀? 編者按:本文為《Cube 技術(shù)解讀》系列第六篇文章,作者是螞蟻集團(tuán)客戶端工程師晟侖,對(duì)于 Cube 渲染引擎來說,在 OTT 上,面對(duì)的是一個(gè)全新的場(chǎng)景,既需要解決 OTT 設(shè)備的性能問題,也需要更合理的焦點(diǎn)引擎能力的支持,本篇帶來大屏小程序探索實(shí)踐,歡迎查閱~
第一篇:支付寶新一代動(dòng)態(tài)化技術(shù)架構(gòu)與選型綜述 | Cube 技術(shù)解讀
第二篇:Cube 卡片技術(shù)棧詳解 | Cube 技術(shù)解讀
第三篇:Cube 小程序技術(shù)詳解 | Cube 技術(shù)解讀
第四篇:Cube 渲染設(shè)計(jì)的前世今生 | Cube 技術(shù)解讀
第五篇:文本布局性能提升 60%,Inline Text 技術(shù)原理與實(shí)現(xiàn) | Cube 技術(shù)解讀
第六篇:本篇
背景
支付寶客戶端有極強(qiáng)的動(dòng)態(tài)化訴求,不論 iOS 還是 Android 平臺(tái),重新分發(fā)軟件包從時(shí)間上,效率上難以滿足產(chǎn)品運(yùn)營的要求,因此客戶端動(dòng)態(tài)化技術(shù)應(yīng)運(yùn)而生。
Cube 起源于 Native 頁面的動(dòng)態(tài)化訴求,隨著小程序的出現(xiàn),Cube 融入了支付寶小程序技術(shù)棧,產(chǎn)品形態(tài)為輕量級(jí)的支付寶小程序解決方案(相對(duì)于使用瀏覽器作為核心的 Web 小程序)。作為一個(gè)輕量級(jí)引擎,Cube 小程序具有體積小、啟動(dòng)快、內(nèi)存占用低的特點(diǎn)。而在 IOT 領(lǐng)域,因 Cube 以上的優(yōu)勢(shì),于是衍生出了適合大屏的小程序技術(shù)棧。
何為大屏小程序?
所謂大屏小程序,是以 Cube 小程序技術(shù)棧 為載體,運(yùn)行在智能電視或智能機(jī)頂盒等設(shè)備上的一種小程序形態(tài)。這些設(shè)備的主要特點(diǎn)是:
以 Android 系統(tǒng)為主,系統(tǒng)版本普遍較低,有些設(shè)備依然停留在 Android 4.2,Android 4.4 以下設(shè)備占比在40%+;
內(nèi)存低,512MB 以下的設(shè)備占比超過 20%,1GB 以下的設(shè)備占比超過 60%;
CPU 主頻低,雙核占比在 20% 左右,有的只有 1.5GHz;
和手機(jī)設(shè)備相比較,按手機(jī)淘寶的設(shè)備評(píng)分體系為參照的話,全部都是低端設(shè)備。
正是因?yàn)檫@些智能電視或智能機(jī)頂盒天然存在的硬件上的瓶頸,且運(yùn)行在這些智能電視或智能機(jī)頂盒上的Android 應(yīng)用程序在版本發(fā)布上受行業(yè)廣電監(jiān)管以及硬件廠商的限制諸多,每年只有幾次的版本發(fā)布迭代窗口。所以亟需一種更小、更快、更省的動(dòng)態(tài)化技術(shù)棧來解決用戶設(shè)備升級(jí)周期長,客戶端版本長尾問題。而 Cube 小程序技術(shù)棧,從設(shè)計(jì)之初就具備更小、更快、更省的特點(diǎn),因此成為智能電視或智能機(jī)頂盒(以下簡稱為 OTT 設(shè)備的不二選擇。
對(duì)于 Cube 渲染引擎來說,在支付寶錢包中,面對(duì)的是手機(jī)端的場(chǎng)景,而在 OTT 上,面對(duì)的是一個(gè)全新的場(chǎng)景,既需要解決 OTT 設(shè)備的性能問題,也需要更合理的焦點(diǎn)引擎能力的支持。
焦點(diǎn)引擎
何為焦點(diǎn)引擎?上面提到了何為大屏小程序以及大屏小程序運(yùn)行的 OTT 設(shè)備,而這些 OTT 設(shè)備的交互方式,就是通過遙控器來操作,這一點(diǎn)和觸控設(shè)備完全不同。遙控器通過 Android 系統(tǒng)的按鍵系統(tǒng),進(jìn)行事件分發(fā),來實(shí)現(xiàn)應(yīng)用程序的交互,那么這里就不得不提到我們的焦點(diǎn)引擎,也就是 FocusEngine 了。
所謂 FocusEngine,實(shí)際包括幾大部分:FocusNode (焦點(diǎn) View )、FocusTree (焦點(diǎn)樹)、FocusFinder (焦點(diǎn)查找器)、FocusState (焦點(diǎn)狀態(tài))、FocusEffect(焦點(diǎn)效果)。

而原有的 Cube 小程序技術(shù)棧不具備FocusEngine 的能力,也就是說渲染引擎中缺少最后一棵樹 FocusTree,更沒有焦點(diǎn)查找器、焦點(diǎn)狀態(tài)以及焦點(diǎn)效果的支持。關(guān)于 Cube 小程序渲染引擎中?LayoutTree,RenderTree,LayerTree,此處不再進(jìn)行額外贅述,詳細(xì)了解可參見《Cube 渲染設(shè)計(jì)的前世今生》該篇中常見術(shù)語和數(shù)據(jù)模型的介紹。
實(shí)現(xiàn)細(xì)節(jié)
上面我們提到 FocusEngine 包含的幾個(gè)主要部分,下面我們來看看 Cube 小程序渲染引擎中的無名英雄------ Focus 的實(shí)現(xiàn)。
FocusNode (焦點(diǎn) View )
FocusNode 是用于獲取遙控器按鍵事件的對(duì)象,也就是說當(dāng)小程序的 AXML 中一個(gè) view 節(jié)點(diǎn)具備了focusable 屬性時(shí),那么在 Cube 渲染引擎中會(huì)映射成一個(gè) FocusNode 節(jié)點(diǎn),且會(huì)進(jìn)行實(shí)體化。該節(jié)點(diǎn)具備主動(dòng)獲取焦點(diǎn) requestFocus 和主動(dòng)清除焦點(diǎn) clearFocus 的能力,同時(shí)也可以監(jiān)聽 focus 的變化,可接收到 onFocusChange 的回調(diào) onFocus 和 onBlur 事件通知
FocusTree (焦點(diǎn)樹)
FocusTree 是與 Cube 渲染引擎中的 LayerTree 獨(dú)立開的,一棵單獨(dú)的實(shí)體節(jié)點(diǎn)的 Tree,它主要用于維護(hù) LayerTree 中可聚焦 FocusNode 之間的父子關(guān)系。FocusTree 暫時(shí)無法通過單獨(dú)的工具查看這棵樹的結(jié)構(gòu),但掛在樹上的 FocusNode 可通過 DevTools 的 Elements 或 Android 的 LayoutInspector 查看,后續(xù)會(huì)考慮支持進(jìn)行獨(dú)立樹的 dump 后導(dǎo)出方便查看。焦點(diǎn)樹結(jié)構(gòu)示例如下:

FocusFinder (焦點(diǎn)查找器)
FocusFinder 是負(fù)責(zé)焦點(diǎn)搜索邏輯的核心查找器,內(nèi)部維護(hù)著用于從當(dāng)前具有焦點(diǎn)的 FocusNode 中查找給定方向上的下一個(gè)可聚焦 FocusNode 的算法(PS:這里的方向指的是遙控器操作的上下左右)。
在 Cube 的渲染引擎中,無論是 Layout、Render pipline,還是 Tree,代碼均采用 C++ 來實(shí)現(xiàn),而 FocusFinder 的算法實(shí)現(xiàn)亦是如此。我們?cè)?FocusFinder 的實(shí)現(xiàn)上,以 Android 的 FocusFinder 實(shí)現(xiàn)為藍(lán)本,實(shí)現(xiàn)了適合 Cube 渲染引擎的焦點(diǎn)查找算法,去除了 Android 本身的?descendant focusability?支持,采用默認(rèn)FOCUS_AFTER_DESCENDANTS 的查找策略,且基于內(nèi)部 FocusNode 的管理機(jī)制,不再額外提供 UserSpecifiedFocusNode 的支持,并支持了五種優(yōu)先級(jí)查找策略,分別為?CENTER_FIRST(中間對(duì)齊優(yōu)先)、LEFT_FIRST(左對(duì)齊優(yōu)先)、RIGHT_FIRST(右對(duì)齊優(yōu)先)、TOP_FIRST(頂對(duì)齊優(yōu)先)、BOTTOM_FIRST(底對(duì)齊優(yōu)先)。焦點(diǎn)查找策略舉例說明如下:

如上所示,當(dāng)前獲取焦點(diǎn)的 FocusNode 為?A,而 FocusNode?B?和 FocusNode?C?在水平方向上與 Current Focus Node?A?的 Rect 存在交集,因此在內(nèi)部我們會(huì)通過帶權(quán)重比的距離判斷;FocusNode?E,在垂直方向上與 Current Focus Node?A?的 Rect 有交集,而水平方向上沒有,所以更適合作為 FOCUS_UP 的焦點(diǎn)查找,而不是 FOCUS_LEFT 的查找;而 FocusNode?B?和 FocusNode?D,按照 Cube 的渲染引擎的規(guī)則,在水平方向上是允許跨列移動(dòng)焦點(diǎn)的而垂直方向是不允許跨列移動(dòng)焦點(diǎn)的 且 FocusNode?E?會(huì)作為 FOCUS_UP 的優(yōu)先選擇, 因此,此時(shí)進(jìn)行 FOCUS_LEFT 的時(shí)候,會(huì)優(yōu)先選擇 FocusNode?B。
FocusState (焦點(diǎn)狀態(tài))
FocusState 是負(fù)責(zé)維護(hù) FocusNode 節(jié)點(diǎn)焦點(diǎn)狀態(tài)的管理者,內(nèi)部維護(hù) FocusNode 節(jié)點(diǎn)的焦點(diǎn)狀態(tài),因?yàn)樵?AXML 下,當(dāng)一個(gè) View 節(jié)點(diǎn)獲得 focusable 屬性時(shí),那么此時(shí)該節(jié)點(diǎn)會(huì)被標(biāo)記成 FocusNode 節(jié)點(diǎn)。當(dāng) Android 系統(tǒng)按鍵分發(fā)時(shí),F(xiàn)ocusFinder 接收到查找的命令,會(huì)從 FocusTree 中進(jìn)行 FocusNode 的查找,當(dāng)找到最合適的 FocusNode 節(jié)點(diǎn)時(shí),那么此時(shí)該 FocusNode 需要標(biāo)記自己的 FocusState 為 focused 狀態(tài),與此同時(shí),假設(shè)內(nèi)部的 child node 沒有 FocusNode,但有葉子節(jié)點(diǎn) text 或 image,那么此時(shí)會(huì)標(biāo)記 text 或 image 節(jié)點(diǎn)為 selected 狀態(tài)。
FocusEffect (焦點(diǎn)效果)
FocusEffect 主要用來表示不同的節(jié)點(diǎn)對(duì)應(yīng)的 FocusState 的焦點(diǎn)效果,在前端開發(fā)者視角下,主要通過 CSS 的偽類 :focus 來實(shí)現(xiàn),如下代碼片段:
實(shí)際效果
如下圖所示,高亮的 Item 所在的節(jié)點(diǎn)為當(dāng)前獲得焦點(diǎn)的 FocusNode:

??體驗(yàn)優(yōu)化
下面看下在 OTT 設(shè)備上 Cube 小程序的基礎(chǔ)性能數(shù)據(jù):(以淘寶特價(jià)版小程序?yàn)槔?

因優(yōu)化環(huán)節(jié)涉及到整體小程序技術(shù)棧,所以這里簡單提一下小程序基礎(chǔ)設(shè)施中的幾大部分,其中包括:容器,前端框架,Cube 渲染引擎,腳本引擎。主要性能優(yōu)化手段包括但不限于以下內(nèi)容:
包大?。?/strong>移除 OTT 設(shè)備不需要的能力模塊,移除 AntUI、安全數(shù)據(jù)庫、permission 管控模塊,共享apk 宿主內(nèi) so。
腳本引擎:在支付寶錢包移動(dòng)端上使用 JSC/V8 作為 JS 代碼的執(zhí)行引擎,IOT 設(shè)備上使用的是 QuickJS。
內(nèi)存占用:
靜態(tài)區(qū)塊優(yōu)化;
JNI Global Reference 優(yōu)化;
Activity Context 上下文,虛擬機(jī)和 Native 的解耦,防止 Context 被 Native 持有,造成內(nèi)存泄露;
Native 中渲染樹相關(guān)內(nèi)存優(yōu)化,內(nèi)存泄露檢測(cè)處理。
啟動(dòng)性能:
虛擬機(jī)優(yōu)化方面,使用 Class Verify 抑制 + GC 抑制;
優(yōu)化 Android InvocationHandler 動(dòng)態(tài)代理在中低端設(shè)備耗時(shí)問題;
小程序產(chǎn)物 Bytecode 能力支持,減少小程序產(chǎn)物在腳本引擎下 Parse 和 AST 的階段耗時(shí),直接執(zhí)行Bytecode。
開發(fā)體驗(yàn)
上面我們介紹完了和 FocusEngine 相關(guān)的實(shí)現(xiàn)細(xì)節(jié),相信大家對(duì)于 FocusEngine 所包含的幾個(gè)主要部分有了初步的認(rèn)識(shí)和了解。通過上述關(guān)于 FocusNode 節(jié)點(diǎn)以及 FocusEffect 偽類的代碼片段,不難看出,只要使用了 Cube 小程序技術(shù)棧,那么開發(fā)一個(gè)大屏小程序,和開發(fā)一個(gè)普通的支付寶小程序差異性是微乎其微的。
除了開發(fā)方式和普通支付寶小程序完全無二之外,在調(diào)試工具上也是可以使用 Chrome DevTools 來進(jìn)行編輯和修改相應(yīng)的可 Focus 的 DOM 節(jié)點(diǎn)的,如下圖所示:

探索與應(yīng)用
從擁抱 Native 開發(fā),到擁抱動(dòng)態(tài)化小程序技術(shù)棧開發(fā),即解決了碎片化設(shè)備下的長尾瓶頸問題,又是產(chǎn)品技術(shù)的架構(gòu)升級(jí)。在 CIBN 酷喵影視下,我們和業(yè)務(wù)方一道進(jìn)行了大膽的創(chuàng)新和探索,最終實(shí)現(xiàn)了多種 Cube 小程序的產(chǎn)品形態(tài)。其中包括用于雙十一戰(zhàn)役的直播間半屏小程序、用于桌面首頁大作業(yè)的 Tab 小程序、用于搜索廣告下的嵌入式小程序、以及用于業(yè)務(wù)運(yùn)營的全屏小程序,效果分別如下:

未來思考和展望
關(guān)于渲染引擎本身的思考,未來會(huì)進(jìn)一步打磨整體的渲染鏈路,在性能上提升 Cube 小程序的啟動(dòng)性能。眾所周知,解釋性語言每次運(yùn)行時(shí)都需要通過解釋器對(duì)程序進(jìn)行動(dòng)態(tài)解釋和執(zhí)行。而這個(gè)過程少不了從 Parse 到AST,再從 AST 到 Bytecode 的過程,未來會(huì)進(jìn)一步減少 Parse 和 AST 的過程,能充分發(fā)揮腳本引擎對(duì)Bytecode 的支持,提升啟動(dòng)性能。另外,也會(huì)逐漸減少對(duì) Platform 層的依賴,使 Platform 層更輕量化,充分降低 Cube 渲染系統(tǒng)和平臺(tái)本身的渲染系統(tǒng)的耦合,更好的完善提升渲染本身的能力。
在業(yè)務(wù)場(chǎng)景探索上,未來會(huì)與更多的二三方進(jìn)行合作,無論是大屏端的 App,還是桌面 launcher,幫助他們解決版本長尾效應(yīng)和業(yè)務(wù)動(dòng)態(tài)性問題,當(dāng)然也會(huì)有更多的場(chǎng)景的支持,譬如小游戲,3D 等。
如果你需要一種更小、更快、更省的動(dòng)態(tài)化渲染技術(shù)棧,且具有更好的開發(fā)體驗(yàn)和行業(yè)共識(shí),那么 Cube 也許是一個(gè)不錯(cuò)的選擇。