LuaView 高性能、动态化、跨平台应用开发引擎—聚划算动态化之路

阅读数:3316 2016 年 5 月 10 日 17:24

1. 移动开发困局

业务快速发展的互联网产品,其移动应用往往会遇到版本迭代速度跟不上需求变更速度的问题。这时候让应用具有动态化能力就显得尤为重要。所谓的动态化是指应用不发版实现内容动态更新的能力,这里的应用内容不仅限于基本信息(如售卖的商品信息),而且涉及应用的主体框架、信息结构等深层信息(如页面整体排版、布局)。比如聚划算 3.8 大促,可能需要临时对线上活动进行一个大的调整,如果采用 Native 技术实现的话,正常的发版节奏显然无法支持这种变更,但如果应用具有动态化能力的话,就可以通过动态发布解决上面的问题。

为了达到应用内容动态更新的目的,业内先后出现过很多动态化方案。有部分 Native、部分 Html5 的混合架构 Hybrid App,这种方案以 H5 的动态性为基础,通过定义 Native 的扩展(Bridge)来实现动态化;有约定数据结构,使用 Native 进行渲染的 Native View 方案,通过修改预定结构中的数据,实现动态化;有现在火热的 ReactNative 技术,通过 JavaScript 脚本引擎支持页面 DOM 转换和逻辑控制来实现动态化;还有开源界一大批小众的动态化方案。这些动态化方案都能一定程度上赋予 APP 动态化能力,但是每种方案都有其不太让人满意的缺陷以及能力瓶颈,如 Hybrid 的 H5 部分体验较差;Native View 结构变化不够灵活,不支持逻辑的动态化;ReactNative 的 JS 引擎过重,不适合做长列表等。总之,尚未出现一种可以一统江湖的动态化方案。

聚划算目前正处在业务高速增长的时期,业务需求应接不暇,中间还穿插各种需求变更,基本的发版节奏已经很难满足业务需求,而 h5 的体验又不能很好地支持业务,能否构建一套 Native 动态化方案就变得非常迫切。在这种情况下,聚划算开始了自己的动态化之路。

在最初的时候,我们的工程师采用 Native View 方案构建了一套名为 Box 的简单动态化系统(如图)。通过预先约定好前后端 Json 数据格式和解析规则,在 Android、iOS 端以相同的方式解析、渲染服务端数据,从而实现两个端的简单动态化页面。Box 能做到图片以及链接的动态配置与变更,但 Box 最主要的问题是只能下发结构预先定义的数据,并且不能下发处理逻辑,这就造成 Box 系统的适用范围非常有限,只能处理预定结构的服务端数据,无法构建复杂的 UI,无法支持个性化 Native 页面。

LuaView高性能、动态化、跨平台应用开发引擎—聚划算动态化之路

为了更好地支持页面动态化,支持复杂 UI,支持逻辑下发,我们又继续向更高级的方案出发,这就是接下来要介绍的方案—LuaView,说到 LuaView,首先要从 Lua 语言说起。

2. Lua 脚本语言新探索

Lua 脚本语言的设计初衷是可以方便地嵌入到其他语言中,为应用程序提供灵活的扩展和定制功能,现实中的 Lua 更是不仅可以作为应用程序的扩展,还可以作为应用程序的配置文件。同时 Lua 脚本语言已经被广泛地用在各种场合以及应用程序中,游戏领域有大名顶顶的 Minecraft、魔兽世界、愤怒的小鸟等;应用领域有 Adobe Photoshop Lightroom。

Lua 脚本语言的内核非常小,官方 Lua 5.0.2 的内核只有不到 120KB,这使得 Lua 脚本的启动非常迅速,在所有脚本引擎中,Lua 是平均意义上最快的。在嵌入式和移动领域,体积小,启动快是一个极大的优势。此外,Lua 脚本还有容易理解,易于维护等优势。

Lua 脚本语言有着极强的可扩展能力。虽然 Lua 并不象其它许多”大而全”的语言那样,包括很多功能,比如网络通讯、图形界面等,但是 Lua 提供了非常易于使用的扩展接口和机制,可以轻松通过宿主语言完成能力扩展。

总之,Lua 脚本语言具有可扩展性强、简单、高效、占用体积小、启动速度快等诸多优势,同时已经被业界使用多年,有着许多成功案例,是动态化方案首选。

在聚划算中最普遍的动态化需求是开发一个活动页面,基础活动页面的开发需要两种能力,一种是逻辑处理能力,这个 Lua 本身已经具备,一种是 UI 视图构建能力,这个 Android、iOS 原生已经支持,高级活动页面的开发可能还需要原生系统的其他能力,如网络、存储、硬件控制等,这些 Android、iOS 原生系统也已经支持,因而我们的动态化方案核心就变成了如何将 Android、iOS 原生的 UI、网络、存储、硬件控制等能力桥接到 Lua 层,有了这些能力,我们的动态化方案就可以支持 UI 动态搭建、脚本、资源、逻辑动态下发。借助 Lua 语言的可扩展性,我们可以很方便地在 Native 跟 Lua 之间搭建起桥梁,将 Native 的各种能力迁移到 Lua 层。

3. LuaView 设计原则

在 Native 跟 Lua 交互的诸多能力中,以 UI 视图构建能力最为基础,因而我们将最终产出的动态化方案命名为 LuaView,意为使用 Lua 构建 Native UI。

使用 Lua 脚本语言实现 Android、iOS 动态化,面临最大的一个挑战是:避免重新开发一套 UI 库的前提下,在 Android、iOS 系统之间构建一套统一的 Lib 库,并且保证两个端的 Lua 脚本代码一致,特性一致,做到 Write Once Run Both。

为了避免大动干戈开发一套 UI 库,我们选择借用两个平台的原生 UI 库。同时我们选择了现有的成熟的 Lua 引擎(LuaJ & LuaC),并稍作修改以适应移动端的需求,通过构建桥接平台,小心地设计 Lua 层 API,最终做到了 Write Once Run Both,并且上层 API 表现上也很自然。

3.1 LuaView SDK 整体架构

LuaView高性能、动态化、跨平台应用开发引擎—聚划算动态化之路

如图,LuaView SDK 的整体架构可以表示为五层。

自下而上第一、二层依次是 OS 层和 Framework 层,分别表示了 Android、iOS 以及对应的框架层。

紧接着是 Lua 虚拟机,在 Android、iOS 平台分别是 LuaJ 和 LuaC,两个虚拟机都是目前两个语言中用的最广泛,最稳定的虚拟机。

处在第三层的还有脚本管理模块以及安全控制模块,它们分别负责 Lua 本地脚本管理(包括脚本的解包、验证、加解密、解压缩等工作)和 Lua 脚本的安全校验工作(脚本完整性校验以及脚本安全校验等)。

处在第四层的是 LuaView 的核心 Lib 库,包括两部分,一部分是 Lua UI Lib,主要是所有的 UI 组件(如 Button、Label、Image、TableView 等);一部分是 Lua Non-UI Lib,主要是所有非 UI 组件(如 Http、Json、Audio 等)。

处在最上层的是 Lua 业务脚本代码以及 Lua 层的 Lib 库(方便第三方使用的 Lua 写的 Lib 库)。

3.2 LuaView 两个重要设计原则。

Write Once Run Both:

LuaView 的一条重要设计原则就是同一份逻辑只写一份代码,这需要在设计 SDK 的时候尽可能得考虑到两个端的共性跟特性,将 API 构建在两个端的共性领域中,对于两端的特性领域则交由各自的 Native 部分来实现。目前 LuaView SDK 的 Android 端、iOS 端已经完成输出统一的 Lua 接口,同时保证 API 特性一致,做到一份脚本两个端运行出来的效果一致。做到一份脚本跨 Android、iOS 平台运行。

LuaView高性能、动态化、跨平台应用开发引擎—聚划算动态化之路

Simple & Easy:

LuaView 的另一个设计原则是保持 Lua 语言的简单和易用。核心 UI 库上,所有的 API 做到精简,能够使用脚本实现的,尽量避免使用 Native 来实现。设计 API 的时候保证所有的 LuaView 语言层使用 Lua 原生语法,所有的 UI 控件库接口跟 Android、iOS 保持一致风格,方便两个端开发人员的迁移。

4. LuaView 动态能力

LuaView 的动态能力基本上可以跟 Html5 匹敌,做到数据、资源、页面结构,甚至代码逻辑的动态下发,并且 LuaView 支持本地代码 & 资源缓存,可以有效降低每次加载的时间,减少不必要的服务器交互,提升页面加载速度。

LuaView 既可以作为完整页面,也可以作为某个视图组件使用(这是 Html5 很难做到的一点),同时还支持 Native 组件注入,很好地满足了完整 APP,现有 APP 部分功能替换以及现有组件接入 LuaView 动态能力等场景。

LuaView高性能、动态化、跨平台应用开发引擎—聚划算动态化之路

页面级场景:

LuaView 可以承载独立页面,一个页面的所有功能都使用 Lua 脚本开发,同时 SDK 提供了脚本 & 资源缓存,脚本下载 & 解包等功能,能够快速支持业务开发。新开发一个完整页面的情况下,非常适合此种场景。

组件级别场景:

LuaView 可以作为独立的 UI 组件,嵌入到任何视图树中,同时该块 UI 组件可以跟 Native 交互,具备动态更新能力。对于页面已经开发完成,但某块成熟业务中某些内容需要频繁变更的时候,非常适合此种场景。

Native 组件注入场景:

将一个应用原有的 Native UI 组件作为子 UI 注入到 LuaView 中,同时支持该 Native UI 组件调用 Lua 层代码,Lua 代码也可以做到动态更新,从而实现 Native UI 组件功能的动态变更。对于页面已经开发完成,但某块 UI 处理逻辑需要动态变动的时候,非常适合此种场景。

5. LuaView 现状 & 后续工作

LuaView 目前已经在线上运行将近半年时间,支持了聚划算多个垂直业务,表现稳定。

后续 LuaView 主要围绕以下三方面进行工作:

1. API 完善

LuaView 是构建在两个不同平台的统一框架,为了在 Lua 层屏蔽掉两个平台各自差异,需要我们持续完善我们的 API 设计,其中涉及到增加新的共性 API,去除老的不兼容 API,采用更优方式实现 API 统一等。

2. 性能 & 结构优化

LuaView 毕竟是在已有的 Native Framework 框架上又搭建起来的新层,性能必然会有损耗,如何将这种损耗降低到最低,达到最优,是我们一直在做的事情。另外,为了更方便的支持上层业务开发,需要将 Lua API 以及结构梳理地更顺畅,进一步减少学习成本。

3. 文档、Demo、支持工具丰富化

LuaView 尚处在发展前期,各种文档支持、Demo 示例,以及支持工具都还不够完善,需要 LuaView 团队以及整个社区的支持。

6. 开源

为了更好地回馈社区,提升整个无线社区的开发效率,同时也让更多的人参与进来,借助社区的力量提升整个项目质量,让 LuaView 真正成为一个能够服务更多团队的框架。我们已经将 LuaView 项目整体开源,项目地址 https://github.com/alibaba/LuaViewSDK

目前我们开源的主要内容包括 LuaView-iOS、LuaView-Android、LuaViewDebugger 等。为了方便大家入手,我们还整理了所有的 API,形成了 APIDoc,供大家参阅。此外我们还有丰富的测试脚本,可以帮助大家快速入门。

欢迎大家一起交流学习。

收藏

评论

微博

用户头像
发表评论

注册/登录 InfoQ 发表评论