大屏小程序探索实践 | Cube 技术解读
简介: 支付宝客户端有极强的动态化诉求,不论 iOS 还是 Android 平台,重新分发软件包从时间上,效率上难以满足产品运营的要求,因此客户端动态化技术应运而生。 Cube 起源于 Native 页面的动态化诉求,随着小程序的出现,Cube 融入了支付宝小程序技术栈,产品形态为轻量级的支付宝小程序解决方案(相对于使用浏览器作为核心的 Web小程序)。作为一个轻量级引擎,Cube 小程序具有体积小、启动快、内存占用低的特点。而在IOT领域,因Cube以上的优势,于是衍生出了适合大屏的小程序技术栈。
所谓大屏小程序,是以 Cube 小程序技术栈 为载体,运行在智能电视或智能机顶盒等设备上的一种小程序形态。这些设备的主要特点是:
- 以 Android 系统为主,系统版本普遍较低,有些设备依然停留在 Android 4.2,Android 4.4 以下设备占比在40%+;
- 内存低,512MB 以下的设备占比超过 20%,1GB 以下的设备占比超过 60%;
- CPU 主频低,双核占比在 20% 左右,有的只有 1.5GHz;
- 和手机设备相比较,按手机淘宝的设备评分体系为参照的话,全部都是低端设备。
正是因为这些智能电视或智能机顶盒天然存在的硬件上的瓶颈,且运行在这些智能电视或智能机顶盒上的Android 应用程序在版本发布上受行业广电监管以及硬件厂商的限制诸多,每年只有几次的版本发布迭代窗口。所以亟需一种更小、更快、更省的动态化技术栈来解决用户设备升级周期长,客户端版本长尾问题。而 Cube 小程序技术栈,从设计之初就具备更小、更快、更省的特点,因此成为智能电视或智能机顶盒(以下简称为 OTT设备的不二选择。
对于 Cube 渲染引擎来说,在支付宝钱包中,面对的是手机端的场景,而在OTT上,面对的是一个全新的场景,既需要解决 OTT 设备的性能问题,也需要更合理的焦点引擎能力的支持。
焦点引擎
何为焦点引擎?上面提到了何为大屏小程序以及大屏小程序运行的 OTT 设备,而这些 OTT 设备的交互方式,就是通过遥控器来操作,这一点和触控设备完全不同。遥控器通过 Android 系统的按键系统,进行事件分发,来实现应用程序的交互,那么这里就不得不提到我们的焦点引擎,也就是 FocusEngine 了。
所谓 FocusEngine,实际包括几大部分:FocusNode (焦点 View )、FocusTree (焦点树)、FocusFinder (焦点查找器)、FocusState (焦点状态)、FocusEffect(焦点效果)。
而原有的 Cube 小程序技术栈不具备FocusEngine 的能力,也就是说渲染引擎中缺少最后一棵树 FocusTree,更没有焦点查找器、焦点状态以及焦点效果的支持。关于Cube 小程序渲染引擎中 LayoutTree,RenderTree,LayerTree,此处不再进行额外赘述,详细了解可参见之前文章介绍《Cube 渲染设计的前世今生》中常见术语和数据模型的介绍。
实现细节
上面我们提到 FocusEngine 包含的几个主要部分,下面我们来看看 Cube 小程序渲染引擎中的无名英雄------ Focus 的实现。
FocusNode (焦点 View )
FocusNode 是用于获取遥控器按键事件的对象,也就是说当小程序的 AXML 中一个 view 节点具备了focusable 属性时,那么在 Cube 渲染引擎中会映射成一个 FocusNode 节点,且会进行实体化。该节点具备主动获取焦点 requestFocus 和主动清除焦点 clearFocus 的能力,同时也可以监听 focus 的变化,可接收到 onFocusChange 的回调 onFocus 和 onBlur 事件通知
<view id="focus-control" class="button" focusable="true" onFocus="handleFocus"
onBlur="handleBlur"> doRequestFocus() {
my.createSelectorQuery().select('#focus-control').node().exec(function(ret) {
const ref = ret && ret[0];
ref.requestFocus();
})
}
FocusTree (焦点树)
FocusTree 是与 Cube 渲染引擎中的 LayerTree 独立开的,一棵单独的实体节点的 Tree,它主要用于维护 LayerTree 中可聚焦 FocusNode 之间的父子关系。FocusTree 暂时无法通过单独的工具查看这棵树的结构,但挂在树上的 FocusNode 可通过 DevTools 的 Elements 或 Android 的 LayoutInspector 查看,后续会考虑支持进行独立树的 dump 后导出方便查看。焦点树结构示例如下:

FocusFinder (焦点查找器)
FocusFinder 是负责焦点搜索逻辑的核心查找器,内部维护着用于从当前具有焦点的 FocusNode 中查找给定方向上的下一个可聚焦 FocusNode 的算法(PS:这里的方向指的是遥控器操作的上下左右)。
在 Cube 的渲染引擎中,无论是 Layout、Render pipline,还是 Tree,代码均采用 C++ 来实现,而FocusFinder 的算法实现亦是如此。我们在 FocusFinder 的实现上,以 Android 的 FocusFinder 实现为蓝本,实现了适合 Cube 渲染引擎的焦点查找算法,去除了 Android 本身的 descendant focusability 支持,采用默认FOCUS_AFTER_DESCENDANTS 的查找策略,且基于内部 FocusNode 的管理机制,不再额外提供UserSpecifiedFocusNode 的支持,并支持了五种优先级查找策略,分别为CENTER_FIRST(中间对齐优先)、LEFT_FIRST(左对齐优先)、RIGHT_FIRST(右对齐优先)、TOP_FIRST(顶对齐优先)、BOTTOM_FIRST(底对齐优先)。焦点查找策略举例说明如下:

如上所示,当前获取焦点的 FocusNode 为 A,而 FocusNode B 和 FocusNode C 在水平方向上与 Current Focus Node A 的 Rect 存在交集,因此在内部我们会通过带权重比的距离判断;FocusNode E,在垂直方向上与Current Focus Node A 的 Rect 有交集,而水平方向上没有,所以更适合作为 FOCUS_UP 的焦点查找,而不是FOCUS_LEFT 的查找;而 FocusNode B 和 FocusNode D,按照 Cube 的渲染引擎的规则,在水平方向上是允许跨列移动焦点的而垂直方向是不允许跨列移动焦点的 且 FocusNode E 会作为 FOCUS_UP 的优先选择, 因此,此时进行 FOCUS_LEFT 的时候,会优先选择 FocusNode B。
FocusState (焦点状态)
FocusState 是负责维护 FocusNode 节点焦点状态的管理者,内部维护 FocusNode 节点的焦点状态,因为在 AXML 下,当一个 View 节点获得 focusable 属性时,那么此时该节点会被标记成 FocusNode 节点。当Android 系统按键分发时,FocusFinder 接收到查找的命令,会从 FocusTree 中进行 FocusNode 的查找,当找到最合适的 FocusNode 节点时,那么此时该 FocusNode 需要标记自己的 FocusState 为 focused 状态,与此同时,假设内部的 child node 没有 FocusNode,但有叶子节点 text 或 image,那么此时会标记 text 或 image 节点为 selected 状态。
FocusEffect (焦点效果)
FocusEffect 主要用来表示不同的节点对应的 FocusState 的焦点效果,在前端开发者视角下,主要通过 CSS 的伪类 :focus 来实现,如下代码片段:
.button {
margin-top: 30rpx;
margin-left: 15rpx;
width: 450rpx;
height: 200rpx;
border: 2rpx red solid;
}
.button:focus {
border: 2rpx blue solid;
}
如下图所示,高亮的 Item 所在的节点为当前获得焦点的 FocusNode:

下面看下在 OTT 设备上 Cube 小程序的基础性能数据:(以淘宝特价版小程序为例)

因优化环节涉及到整体小程序技术栈,所以这里简单提一下小程序基础设施中的几大部分,其中包括:容器,前端框架,Cube 渲染引擎,脚本引擎。主要性能优化手段包括但不限于以下内容:
- 包大小:移除 OTT 设备不需要的能力模块,移除 AntUI、安全数据库、permission 管控模块,共享apk 宿主内 so。
- 脚本引擎:在支付宝钱包移动端上使用 JSC/V8 作为 JS 代码的执行引擎,IOT 设备上使用的是 QuickJS。
- 内存占用:
- 静态区块优化;
- JNI Global Reference 优化;
- Activity Context 上下文,虚拟机和 Native 的解耦,防止 Context 被 Native 持有,造成内存泄露;
- Native 中渲染树相关内存优化,内存泄露检测处理。
- 启动性能:
- 虚拟机优化方面,使用 Class Verify 抑制 + GC 抑制;
- 优化 Android InvocationHandler 动态代理在中低端设备耗时问题;
- 小程序产物 Bytecode 能力支持,减少小程序产物在脚本引擎下 Parse 和 AST 的阶段耗时,直接执行Bytecode。
上面我们介绍完了和 FocusEngine 相关的实现细节,相信大家对于 FocusEngine 所包含的几个主要部分有了初步的认识和了解。通过上述关于 FocusNode 节点以及 FocusEffect 伪类的代码片段,不难看出,只要使用了 Cube 小程序技术栈,那么开发一个大屏小程序,和开发一个普通的支付宝小程序差异性是微乎其微的。
除了开发方式和普通支付宝小程序完全无二之外,在调试工具上也是可以使用 Chrome DevTools 来进行编辑和修改相应的可 Focus 的 DOM 节点的,如下图所示:

从拥抱 Native 开发,到拥抱动态化小程序技术栈开发,即解决了碎片化设备下的长尾瓶颈问题,又是产品技术的架构升级。在 CIBN 酷喵影视下,我们和业务方一道进行了大胆的创新和探索,最终实现了多种 Cube 小程序的产品形态。其中包括用于双十一战役的直播间半屏小程序、用于桌面首页大作业的 Tab 小程序、用于搜索广告下的嵌入式小程序、以及用于业务运营的全屏小程序,效果分别如下:

关于渲染引擎本身的思考,未来会进一步打磨整体的渲染链路,在性能上提升 Cube 小程序的启动性能。众所周知,解释性语言每次运行时都需要通过解释器对程序进行动态解释和执行。而这个过程少不了从 Parse 到AST,再从 AST 到 Bytecode 的过程,未来会进一步减少 Parse 和 AST 的过程,能充分发挥脚本引擎对Bytecode 的支持,提升启动性能。另外,也会逐渐减少对 Platform 层的依赖,使 Platform 层更轻量化,充分降低 Cube 渲染系统和平台本身的渲染系统的耦合,更好的完善提升渲染本身的能力。
在业务场景探索上,未来会与更多的二三方进行合作,无论是大屏端的 App,还是桌面 launcher,帮助他们解决版本长尾效应和业务动态性问题,当然也会有更多的场景的支持,譬如小游戏,3D等。
如果你需要一种更小、更快、更省的动态化渲染技术栈,且具有更好的开发体验和行业共识,那么 Cube 也许是一个不错的选择。
原文链接:https://click.aliyun.com/m/1000354383/
本文为阿里云原创内容,未经允许不得转载。
大屏小程序探索实践 | Cube 技术解读的更多相关文章
- Cube 技术解读 | Cube 小程序技术详解
本文为<Cube 技术解读>系列第三篇文章,之前上线的<支付宝新一代动态化技术架构与选型综述>与<Cube卡片技术栈解读>欢迎大家回顾. 魔方卡片(Cube)已在「 ...
- 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理
[微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...
- 京东小程序接入ARVR的技术方案和性能调优
作者:京东零售 戴旭 京东小程序是一个开放技术平台,正在被越来越多的头部品牌选择,用于站内私域流量的营销和运营.诸如各种日化.奢侈品等品牌对ARVR有较多的诉求,希望京东小程序引擎提供一些底层能力,叠 ...
- 小程序webview实践
小程序webview实践 -- 张所勇 大家好,我是转转开放业务部前端负责人张所勇,今天主要来跟大家分享小程序webview方面的问题,但我并不会讲小程序的webview原理,而我主要想讲的是小程序内 ...
- 微信小程序开发实践
目录 项目是否适合移植到小程序上? 概要介绍 实践得到的经验 规则 小程序不支持的 新特性 小窍门 会话管理 进阶 项目是否适合移植到小程序上? 小程序由于微信提供了一些组件,在微信中的一些体验确实不 ...
- 【微信小程序项目实践总结】30分钟从陌生到熟悉
前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05-日历组件的实现 4. 微信小程序开发04-打造自 ...
- 【小程序】微信小程序开发实践
帐号相关流程 注册范围 企业 政府 媒体 其他组织 换句话讲就是不让个人开发者注册. :) 填写企业信息 不能使用和之前的公众号账户相同的邮箱,也就是说小程序是和微信公众号一个层级的. 填写公司机构信 ...
- appium+java(五)微信小程序自动化测试实践
前言: 上一篇<appium+java(四)微信公众号自动化测试实践>中,尝试使用appium实现微信公众号自动化测试,接着尝试小程序自动化,以学院小程序为例 准备工作 1.java-cl ...
- 大学课后答案微信小程序项目实践(1)
叨逼叨 还记得以前小编上大学那会苦于课后习题没有答案...到了考试....就像下面这个图一样- 现在,那些同样在纠结于书本后的答案太遥远的同学们,要告诉你们一个好消息,个人历时两周作业的时间开发的小程 ...
- Java小程序—录屏小程序(下半场)
下半场. 上半场,我们我们写了录屏的程序,那么下半场我们的任务是写一个播放器. 设计思路:播放器的思路就是将图片放在一个JScrollPane中顺序播放,所以还是得使用swing组件,并且仍然要使用线 ...
随机推荐
- 求给定两个排序好的数组中第k大的数
这个问题比求两个长度相等的排序数组的上中位数难度要高一点,难就难在不是求中位数了,但是我们要学会举一反三,可以尝试通过分析将求第k大的数转化为求中位数.将数组中不可能的数排除,在剩下可能的数中求中位数 ...
- Linux 运维工程师面试真题-1-必会Linux 操作系统知识
Linux 运维工程师面试真题-1-必会Linux 操作系统知识 运维的整个面试流程其实是非常繁杂的,为了方便大家准备,我们特地在这里给大家整理了 一些 Linux 系统运维相关的面试题,有些问题没有 ...
- 记录--Three.js的简单使用,Three.js在vue3.x中导入.pcd三维模型文件
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 本文说明 本文主要简单介绍了,在Vue3.x项目中如何简单的使用Three.js,导入PCD三维模型文件. 模型显示 项目实现 第一步 首 ...
- Elasticsearch内核解析 - 数据模型篇【转载】
原文链接 Elasticsearch是一个实时的分布式搜索和分析引擎,它可以帮助我们用很快的速度去处理大规模数据,可以用于全文检索.结构化检索.推荐.分析以及统计聚合等多种场景. Elasticsea ...
- C# WinForm 获取执行路径的几种常见方法
//1.获取模块的完整路径. string path1 = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; Co ...
- KingbaseES垃圾回收参数优化之maintenance_work_mem
maintenance_work_mem 参数说明与vacuum过程 maintenance_work_mem , autovacuum_work_mem. 如果没有设置autovacuum_work ...
- Android将数据导入到已有的excel表格_0
用到的jxl2.6.12 jar 包下载地址: https://mvnrepository.com/artifact/net.sourceforge.jexcelapi/jxl/2.6.12
- #dfs,trie#洛谷 4341 [BJWC2010]外星联络
题目 分析 首先时间复杂度\(O(n^2)\)可过,统计子串个数可以用trie或者更高级的方法 可以枚举所有的后缀,然后建一个trie,这样这个trie就可以记录全部的子串 关于字典序排序,深搜的时候 ...
- #子序列自动机,vector#洛谷 3500 [POI2010]TES-Intelligence Test
题目 多组询问查询某个串是否为模式串的子序列 分析 考虑用子序列自动机做,匹配的时候显然选择靠前的,用个vector查询最近的就行了 代码 #include <cstdio> #inclu ...
- Python 元组完全指南2
更新元组 更改元组的值 元组是不可更改的,但有一种变通方法.您可以将元组转换为列表,更改列表,然后将列表转换回元组. 示例: x = ("apple", "banana& ...