2016 NJSD南京软件开发者大会已经过去一个多月时间,会上有幸跟现场的朋友一起分享《跨平台移动应用开发架构实践》的话题,在这段时间里收到一些开发者的反馈和疑问,很高兴有那么多开发者对跨平台移动应用开发技术感兴趣。
也有开发者反映说大会提供的pdf材料内容有缺失,这里提供一份我自己转格式的pdf(点此下载),应该是没有缺少内容,也借这个机会对演讲的内容做个补充说明,用相对好理解的方式再阐述一下ExMobi的技术架构选型的原因和在实践中遇到的困难和问题如何解决,以供开发者参考。
ExMobi的产品背景
ExMobi是一个跨平台的移动应用开发平台,起初是作为烽火星空应用交付的一个重要平台。平台提供高性能、高质量的快速交付移动应用的能力,为提升企业客户特别是集团大客户的服务水平提供基础保障。
ExMobi产品其实包含了客户端、服务端和开发工具等多个组成部分,涉及到跨平台这块的技术这块主要是客户端部分,后续有机会的话我们再来分享ExMobi的服务端SOA架构实现和开发工具MBuilder基于RPC的定制化开发实现。
下面进入正题。
主流跨平台移动开发技术架构介绍
跨平台移动应用开发架构主要包括三类:Hybrid架构、解释型架构和交叉编译架构。
Hybrid架构是我们最常见的类PhoneGap的以webview套壳应用为核心技术的架构,这种方式以HTML5作为UI展现能力,通过JS调用本地能力;
解释型架构是采用一种自定义的中间语言描述UI和能力,在不同平台上采用原生的方式解析这个中间语言以达到完全原生的效果,这种方式的本质是纯原生的,运行方式类似于曾经风靡的FLASH的Runtime机制,而且中间语言的更新不需要重新打包,可以像HTML一样动态更新;
交叉编译架构是采用一种语言编译成另一种语言的过程,在跨平台实现中就是通过编写一种语言编译成Android JAVA程序和iOS Object-C程序,甚至Windows Phone等平台的程序;
ExMobi为什么选择解释型架构
经过对不同技术架构做了一些必要的预研工作,大致总结不同架构存在的问题:
1.Hybrid架构是以HTML5为主,原生为辅;解释型和交叉编译本质是原生的,以原生为主,HTML5为辅,但是完全使用HTML5也是可以做到的,这种情况其实就是Hybrid的。所以,实际上解释型和交叉编译型架构都包含了Hybrid架构,支持Hybrid架构的任何特性,并且架构更优;
2.Hybrid依赖的是HTML5实现跨平台,实际HTML5在不同版本的操作系统上有很多兼容性问题,只是宏观上的跨平台;
3.能实现交叉编译的语言难度较大或者很偏门,不具有普适性,不仅搭建框架难度和复杂度高,开发者使用也非常麻烦;
4.交叉编译的代码具有平台特性是把双刃剑,对逻辑处理需要做多重判断,增加代码维护量;
5.交叉编译的代码具有原生特性,改动即需重新打包升级,不适合快速迭代;
6.解释型架构最大的问题是中间语言的选择,并决定使用的门槛;
作为开发平台,还需要平衡开发和维护的难度,所以从保持原生性能和效率、使用主流开发技术、方便进行升级维护等方面综合考虑,解释型架构不仅可以保持原生的效果还能自由选择中间语言向主流靠拢,而且能够像html一样发布代码,避免应用市场审核耗时。相对于Hybrid架构在性能效率上的硬伤和交叉编译对快速迭代发布的弊端,解释型架构都是比较合适的选择。
架构实施遇到的各种难题
中间语言如何选择?
考虑到开发者使用中间语言的难度,充分利用传统web开发者众多,最终ExMobi选择了类web开发模式,即通过标签、CSS和JS进行移动应用前端开发。
这里的标签是指烽火星空定义的UIXML移动UI规范,实际是使用XML来描述UI组件的类型和样式,Android JAVA或者iOS Object-C都是实现这个规范采用,并采用原生解析来进行UI展示,可以通过CSS技术对UIXML进行渲染,最终形成一个原生View的DOM树。
在UIXML中可以通过JS操作DOM来实现动态页面展示,以及本地能力能力调用,使得原生UI可以跟本地能力交互使用。
下面就是一个典型的UIXML页面:
<!-- ExMobi UIXML(XHTML)文件 -->
<html>
<head>
<meta content="charset=utf-8"/>
<title>Hello World</title>
<script>
<![CDATA[
function doLoad(){
document.getElementById('content').innerHTML = '欢迎参加南京开发者大会';
}
]]>
</script>
</head>
<body onload="doLoad()">
<div id="content" style="text-align: center;">正在加载,请稍后</div>
</body>
</html>
基本上跟web开发类似,但是实际效果确实完全原生的。
比如一般编写UIXML代码就像上图放大镜里的标签代码,实际解析对应的就是原生的某个View来实现。
渲染效率和解析性能如何解决?
解决了中间语言的问题,其实还有更重要的就是解析效率,XML解析和CSS渲染已经是相对成熟的技术,大家到开源社区里可以看到有很多。
而关键的问题在于DOM树结构经常变化的问题,特别是大数据量和网络请求,我们最常见的就是列表无限下拉刷新,以及页面有大量网络图片展示网络堵塞等。
ExMobi的UIXML解析引擎对于组件的加载采用了差量加载和批量处理两种方式。DOM差量加载主要是解决组件重复加载的问题,对于相同的DOM不重复实例化;DOM变化批量处理主要解决DOM结构的变化带来的原生View容器大小频繁或者重复计算的问题,批量处理好处就是UI空间全部计算好之后再进行重绘。除此之外,对于网络请求的适当缓存、懒加载等技术的使用,减少不必要的网络请求资源,按需加载。
如何解决JS执行和绑定问题?
ExMobi中的JS是写在UIXML中的,这是一个原生的View环境,所以当程序打开UIXML的时候并不能像浏览器一样直接运行JS,而是依赖JS执行引擎,将UIXML作为一个JS的运行环境绑定到JS引擎中,当UIXML中有事件或者操作的时候再调用具体的JS函数。ExMobi的JS引擎采用SpiderMonkey,实际能被调用的JS在页面加载之初就已经注册到SpiderMonkey中了,当页面中要执行JS的时候SpiderMonkey会分发到JS函数池中,函数池会去找对应的原生函数来处理并返回结果。
上图就是ExMobi中JS从绑定到执行再到返回结果的完整过程。
如何解决开发调试问题?
做web全端开发的同学都知道,Chrome、火狐等浏览器都提供了开发者工具可以很方便的进行代码调试。但是UIXML是原生的UI,JS操作的都是原生UI或者本地能力,比如摄像头、蓝牙等,所以UIXML代码的调试在实现之初也是非常棘手的问题,也别对于一个原生开发团队来说,去探索类web开发思路也是非常有限的。随着团队能力的不断提升和对不同开发工具的研究,最终从Firefox浏览器内核找到了办法。
ExMobi的JS引擎用的是SpiderMonkey,而SpiderMonkey是mozilla项目的一部分,跟Firefox是同一宗族,所以使用Firefox的调试器可以很方便的调试UIXML和JS。
由于Firefox中并没有UIXML的很多本地能力JS引用,所以我们采用了远程调试,通过在ExMobi的PC模拟器中运行UIXML和JS,执行过程可以在Firefox调试器中查看和断点。
这样就将开发到调试做到闭环。
当然,遇到的问题还不仅仅是这些,篇幅有限,也欢迎大家分享自己的心得。
如何做架构平台化的转变
ExMobi产品产生之初是为了服务内部项目的,后来,烽火星空的众多客户也加入到使用ExMob进行移动应用开发的行列,自己组建开发团队和维护项目,以降低开发成本。正是有8年跨平台移动应用开发的经验,ExMobi产品才从客户的口碑中逐步走向大众开发者。
现在也已经提供了免费版使用,所以也在架构上做了一些改变,能够让ExMobi可以更容易被开发接受和它的平台化使命。
首先是ExMobi架构上的改变,由于ExMobi一直以来都是以原生为主,但是由于自定义原生组件的程度未必能够满足所以场景,ExMobi提供了对webview的封装,并且搭配提供了基于H5的开源移动前端框架Agile Lite帮助开发者快速实现多端开发;另外就是Native Component原生插件扩展,主要是对接各大开放平台,或者开发者自己的实现的特殊效果。
经过UIXML原生UI引擎、webview H5引擎和Native Component原生插件引擎,三大引擎的作用,可以让开发者很容易的结合原生与H5的能力,并且通过JS可以在不同引擎中进行数据交互和业务逻辑开发,满足各种开发需要。
其次就是对目前主流开放平台的热门和实用SDK进行集成,包括百度地图、微信分享、支付宝、讯飞语音、容联云、QQ登录等等,也为面向企业的开发者提供深信服VPN、通付盾安全加固、富士通蓝牙打印机、CA认证等的专业SDK集成,而且源码开放,开发者可以自己修改和扩展,以及集成自己需要的SDK。
结语
ExMobi或许只是跨平台开发架构中的其中一种,无论是哪种架构都有自己的使用场景,这里就跟大家分享这些,未来的技术瞬息万变,还有很多技术需要我们探索,甚至是黑科技的研究,但是ExMobi始终致力于移动应用的交付。