您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
React Native与ExMobi技术路线探索
 
来源:CSDN 作者:黄楠 发布于 2015-12-2
  3000  次浏览      15
 

摘要:本文作者黄楠从框架、原理、组件、扩展方式、开发、调试等角度,分析对比了由Facebook开源的React Native框架和南京烽火星空的ExMobi轻应用框架。

随着Facebook陆续开源React Native的iOS和Android版本,这种以JavaScript来开发原生APP的方式在移动应用开发圈里得到广泛关注,虽然React Native并不是第一个采用JavaScript编写原生APP的产品,但是其独特的设计思想和实现方式是非常值得借鉴的。

而作为国内的移动应用开发平台,同样支持开发原生APP 以及轻应用的ExMobi,在技术架构上又有怎样的不同呢?

这里,笔者就通过亲身体验来剖析React Native与ExMobi在技术架构、开发者受众、成熟度等多维度的异同,从中探索更多移动应用开发技术上的可能与创新,以飨读者。

产品背景

对产品背景的了解,有助于我们对产品的原理、发展等多方面有基础的认识。

React Native官网上的博客不仅很有技术含量,而且还很有情怀,所以我们就从这里入手。下面就是其中一段摘抄:

可以看出由于WEB在移动端差强人意的表现,使得Facebook要寻求两全其美的办法:

所以React Native诞生的了:

而ExMobi则不同,ExMobi完全是为移动设备诞生,从早期的非智能机时代、早期智能机时代的Java、Symbian、Windows Mobile、Brew、Black Berry平台到现在的后智能机时代Android、iOS系统盛行,ExMobi的架构也发生了翻天覆地的变化。这里特指的是ExMobi第五代产品。

ExMobi产品这么多年,架构上也是做了很大调整,但始终不变的是坚持Native原生APP为主线,同时也支持HTML5的webapp模式开发,提倡Native Component+Web Plus的主流开发模式,让开发者可以充分利用原生组件和HTML5混合布局,完全标签化写法,并通过JS将本地能力无缝对接,开发方式灵活。

从React Native和ExMobi的产品背景中,我们可以看到两者的共同点都是为了提高移动应用开发效率,降低开发成本,并都尽可能的结合Native和HTML5的优点,提出了各自的创新开发模式。

原生组件通信原理

React Native通过JavaScript编写APP的方式,乍看以为是以webview提供的现成的JS与原生语言之间的互调,但是如果当我们调试一个React Native程序的时候,在debug视图中是不会看到任何webview被调用的痕迹。所以,实际上React Native并没有使用现成的与webview的通信方法,而是使用了更直接的JS运行环境,比如在iOS中为系统自带的JavaScriptCore。这与Phonegap这类以webview为主的界面展现与本地能力调用的模式有本质上的区别,也是确保React Native高性能和高效率的基础。

有了这个核心基础,我们再来看看React Native是如何通过JS来挂钩到原生UI和本地能力的。

从上图很容易可以看到,开发者通过JS去调用一个React Native提供的方法,实际需要先经过两个桥接封装类,一个JS的桥接,另一个是原生的桥接。两个桥接类之间就是通过前面提到的JS运行环境来通信。JS桥接类的作用是将开发者的调用行为加入到React Native的模块调用队列,同时生成一个回调的ID。Native桥接类的作用是将队列里的调用行为取出来根据模块找到对应的原生UI或者本地能力的函数来执行,并将执行的结果通过回调的ID逐步传递到开发者的JS回调函数中。也就是经过这两个桥接类的相互作用,建立起了JS函数与原生能力的调用序列。

其中不得不提的是React Native进行了虚拟DOM的封装,所有的视图的更新都是虚拟DOM做了一个校验(diff)后最小更新,用内存计算换取UI渲染效率。而开发者可以(不是必须)使用一种叫JSX的语法即可达到像web开发一样使用标签和CSS样式表来开发React Native应用,React Native会将JSX转化为JS语法通过上述通信流程完成原生UI的渲染和本地能力的调用。

1.  var React = require('react-native');

2.
3. var styles = React.StyleSheet.create({

4. text: {

5. color: 'red',

6. backgroundColor: 'white',

7. fontSize: 30,

8. margin: 80,

9. textAlign: 'center'

10. },

11. container: {

12. flex: 1

13. }

14.});

15.

16.class HelloWorld extends React.Component{

17. render() {

18. return React.createElement(React.Text, {style: styles.text},
"Hello World!");

19. }

20.}

21.

22.class Main extends React.Component {

23. render() {

24. return(<React.NavigatorIOS

25. style={styles.container}

26. initialRoute={{

27. title: 'Property Finder',

28. component: HelloWorld,

29. }}/>);

30. }

31.}

上面的代码段就是一个React Native的例子。它定义了两个组件,一个是HelloWorld,一个是Main,其中HelloWorld组件作为Main组件的一部分进行展示。我们可以看到Main组件里有一段XML的标签,这个语法就是JSX语法,当然,如果不习惯这种语法,也可以完全按照HelloWorld组件的定义,全是使用JS来定义。

ExMobi则是通过解析一种叫UIXML的标签并映射到原生组件的方式渲染窗口和界面,这个解析引擎称为UIXML引擎,在UIXML中也是支持CSS样式表和JS语法。

下面的代码就是一个UIXML代码文件:

1.  <!-- ExMobi UIXML(XHTML)文件 -->
2. <html>
3. <head>
4. <meta content="charset=utf-8"/>
5. <title>dom数据注入</title>
6. <script type="text/javascript"src="res:script/exmobi_lite/core.js"></script>
7. <script type="text/javascript"src="res:script/exmobi_lite/template-native.js"></script>
8. <style>
9. button {
10. color : #ff0000;
11. }
12. </style>
13. <script>
14. <![CDATA[
15. function doRender(){
16. //更简单的用法就是直接对dom操作
17. $('#content').renderAfter('res:page/template/my.template','
http://domain/server.jsp', function(h, t, o){
18. //alert($.JSON.stringify(o));
19. });
20. }
21. ]]>
22. </script>
23. </head>
24. <body>
25. <font style="color: #c0392b;">数据注入函数</font>
26. <div style="margin:4 0;">
27. $(selector).renderReplace(str,data, callback);//注入后的数据替换原来dom内的内容
28. </div>
29. <div style="margin:4 0;">
30. $(selector).renderAfter(str,data, callback);//注入后的数据在dom内尾部插入
31. </div>
32. <div style="margin:4 0;">
33. $(selector).renderBefore(str,data, callback);//注入后的数据在dom内顶部插入
34. </div>
35. <div style="text-align: center;">
36. <input id="btn"type="button" value="点击测试" onclick="doRender()"></input>
37. </div>
38. <div id="content"></div>
39. </body>
40.</html>

从上面的代码可以看到很多熟悉的身影——HTML、CSS、JS,所以使用ExMobi开发移动应用跟web开发基本相差无异,而这种开发方式也容易被开发者认为是采用了webview的引擎来实现,实际上并非如此。在ExMobi的原生应用中完全可以一个html文件都不需要创建,也不会产生对webview的调用。

那ExMobi又是如何做到的呢?

ExMobi应用都是从一个UIXML描述文件开始的,此文件中的内容为类似HTML的标签,支持CSS和JS语法,但是并不是标准的HTML。从1至4步骤中,我们可以看到UIXML引擎将UIXML文件解析并渲染为原生组件的过程。这个过程中,会为每一个UIXML组件都生成一个ID,对于部分有生命周期事件(加载完毕、处于激活状态、处于非激活状态、销毁等)的组件会进行JS事件的触发。

第5步就是将UIXML界面中的组件的JS事件和开发者自己定义的函数绑定到UIXML的JS运行环境中。

第6-13步跟React Native类似,也是先经过一个JS桥接类的序列化要执行的函数,然后再映射到原生的函数中来执行。

与React Native不同的是,ExMobi没有虚拟DOM的概念,UIXML描述是直接映射到Native View中的。这种实现方式在操作DOM时,如果不产生容器的变化一般是对性能和效率影响不大的。但是为了保证效率与性能的提高,UIXML提供了原生UI批处理的JS桥接类(window.beignPreferenceChange()与window.endPreferenceChange()),当开发者遇到DOM大量及多次改动,或者无法判断是否会产生较大改动时,可以按需将DOM操作包含在此批处理类中,UIXML引擎会从内存中通过组件的ID来判断组件的状态,使一组在批处理内的DOM结构改变只需一次刷新。

从React Native和ExMobi在原生组件的通信原理中可以看出,这类以原生UI组件为展示基础的开发框架的核心就是对原生组件的封装和桥接技术的使用。但是React Native是从JS文件开始,在JS中可以渲染UI标签,而ExMobi则是从UI标签(UIXML)文件开始,在UIXML中可以绑定JS函数和事件。

且两者的实现都是以Run Time技术为核心理念的,所有的原生组件都是运行中创建的,而不是在一开始就编译好,这与交叉编译的实现方式有本质的不同。Run Time的好处就在于业务逻辑的代码可以实时的载入,不需要重新编译客户端,无须重新打包发布,面对审核严厉的AppStore来说,对开发者无疑是一个很大的利好。

当然,对于原生组件封装的颗粒度和使用的原生组件类,甚至是否Android和iOS的封装是否需要一致也是开发者热衷于讨论的话题。或者下次可以有幸再跟各位分享。

开发与调试

不同的开发者对开发工具的使用习惯各不相同,正所谓工欲善其事,必先利其器,选准了工具才能提高开发效率。那React Native和ExMobi各自使用什么工具进行开发和调试的呢?形式又是怎样的呢?

React Native并没有自主的开发工具。其开发方式是先到官网上下载React Native的安装包,然后使用npm(NodeJS的包管理工具)来安装并下载相关依赖模块。创建工程也是通过npm来完成。创建完的工程包含了Android和iOS的子工程,分别需要各自搭建原生的开发环境方能运行。所以React Native对开发者的要求是需要有一些原生开发的基础的。并且,如果你是要做iOS应用的开发,则需要有一台MAC电脑。

搭建好原生开发环境之后,开发者就可以使用HTML编辑器来通过编写JS文件完成开发,效果查看需要启动相应的编译工具和模拟器的,比如:iOS需要通过XCode来编译应用到模拟器中,代码中可以使用Console类来打印日志到XCode的控制台中查看,但是无法进行debug调试。有一点比较好的是,当JS有改动的时候,无需重新编译就看到修改后的效果,非常方便,这也是有赖于React Native的Run Time机制。

特别的,如果开发者想要在真机上调试,那就有写麻烦了。React Native开发时加载JS的方式是通过启动HTTP接口来动态刷新的,而默认是本机调试的接口地址对应的IP和端口为127.0.0.1:8081,在真机上调试显然是无法连接到此接口的,这就需要开发者自己通过命令来修改,然后编译一个React Native的原生安装包给真机安装好才能连接到想要调试的开发环境中。这个过程比较复杂,无论是对原生开发者还是web开发者来接触React Native开发都需要一定的过渡时间。

并且,由于React Native的原生组件在不同平台上的写法是不同的,Android有自己的组件,iOS也有自己的组件。当开发者开发完某个平台的应用的时候,想要在另一个平台上运行,还需要修改代码符合目标平台的规范。

这也是为什么说React Native是Learn Once , Write Anywhere的原因——使用React Native开发Android和iOS的应用,开发方式是一样的,只是写法稍有不同,可以做到技术经验的积累。

由于React Native的开发和调试方式跟原生类似,此处省略N张截图。

ExMobi具有自主的开发工具叫MBuilder,无论是开发Android还是iOS应用都可以在这里面完成。开发者只需要下载MBuilder安装包进行一键安装即可进行ExMobi应用的创建、开发、模拟器调试、真机调试等一系列简单方便的操作。这主要也是有赖于ExMobi的UIXML引擎在多个平台上的定义是一致的,也就是说写好一套代码就可以在多个平台上运行,无须对代码进行区分修改。

下图为MBuilder的界面,它是基于eclipse的一个插件,自定义了很多内置编辑器,组件拖拽,真机调试等功能,并能在创建应用的时候使用现有模板。

特别的是,ExMobi有个基座的概念的,结合前面介绍Run Time模式,与React Native相似,UIXML、JS和CSS等代码也是要通过HTTP接口加载到基座中就可以运行处原生的界面,为了开发调试方便,基座上可以直接配置IP和端口,所以任何机器上的ExMobi代码可以很方便的可以同步到模拟器或者真机上调试。

下图即为PC版基座模拟器的截图:

更强大的是, 开发者可以在PC版的ExMobi模拟器中对UIXML的JS代码进行调试,并综合Console控制台日志进行错误分析,开发调试跟在Chrom/Firefox中调试JS一样,非常方便。

更强大的是, 开发者可以在PC版的ExMobi模拟器中对UIXML的JS代码进行调试,并综合Console控制台日志进行错误分析,开发调试跟在Chrom/Firefox中调试JS一样,非常方便。

所以,ExMobi提倡的是Write Once , Run Anywhere,在Android和iOS中使用相同的用户体验。当然,ExMobi提供了区分Android和iOS的函数,开发者也可以根据需要做平台差异化展示。

组件的数量和扩展方式

对于开发者来说成熟的组件以及灵活的扩展无疑是对高质量应用的最佳保障。

从React Native官网上大概可以看到其有30个左右的组件,有的仅支持Android,有的仅支持iOS,但是其中的View组件是可以比较灵活的通过组合来形成新的组件。

而且React Native支持组件的扩展,通过原生开发就可以开发出符合自己要求的UI组件。目前市面上也有一些不错的React Native UI组件,比如:表单处理组件、照相/摄像组件、视频播放组件、轮播组件等等,基于Facebook的影响力,未来应该还会涌现出很多优秀的组件插件库。

下面就来亲眼目睹一下:

ExMobi的原生UI组件从官网提供的开发手册中可以看到90+个组件,并且在其公开的原生插件也有30多款,除了基本的UI布局组件,比如:九宫格、列表、下拉刷新、轮播、通讯录、拍照摄像、日期时间选择组件等等。

当然,ExMobi也支持对原生UI和能力的扩展,开发者也可以通过原生开发扩展ExMobi的能力。所以也有很多跟国内广泛使用的SDK结合的原生插件,比如:百度地图、讯飞语音、支付宝、微信/微博分享/登录、汉王名片识别、百度影音播放等等,以及一些专业的企业级SDK集成,比如:深信服VPN、企业版WPS文档编辑、蓝牙打印、身份证识别、CA认证等等。

所以,从本地化的角度看,ExMobi扎根国内,需求比较接地气,更容易满足开发者的需要。而对于React Native想要适应目前的开发环境,还需要不断的定制出更多的符合要求的组件。

下面是从ExMobi论坛上的一些截图:

第一个真不是格瓦拉上截的图哦,ExMobi官网上还有很多比较成熟的UI界面分享,基本可以满足大部分的开发需要。

面向的开发者

从前面的了解, React Native和ExMobi的开发语言都是以类web的标签化+JS开发为主,并且都支持原生组件和能力的扩展,所以,无论是web开发者还是原生程序开发者要使用这两个工具都不是非常难的事情。

这里主要是从React Native和ExMobi的一些宣讲和推广等渠道了解的信息作为判断。

React Native从开发环境的搭建到开发方式上其实都是偏向于原生的,纯粹的web开发者要想很快能够熟练使用React Native甚至说是搭建开发环境似乎还是要多花一些心思的。并且在React Native的宣讲中,仍然是建议原生开发者能够尝试接纳React Native这种新的开发模式,以提高自己的开发效率。或许可以推断,React Native在设计之初所考虑面向的开发者为原生开发者。

ExMobi则把移动应用开发的各个环节都通过MBuilder这个IDE来紧密集合。一键安装的跨平台开发工具和更接近的web开发模式对于传统web开发人员来说不可谓无故意而为之的“嫌疑”,而从官方提供三类开发者,UIXML开发者、HTML5开发者和原生插件开发者来看,如果单纯使用ExMobi来开发,不考虑原生插件,那么其面向的开发者必定的是web开发者。当然

当然,现在全栈式开发越来越多的走进人们的视野,单一的技术已经无法满足开发的需要,或许对不同技术的巧妙应用才能带来下一波的技术创新。这里我们讨论的只是从入门和使用的角度的受众,对技术的不断探索对于程序员来说是不遗余力的。

与HTML5的结合

Native与HTML5从来都不是竞争关系,而更多的是合作关系,只是不同的开发者使用的比例不同罢了。但是如何结合,React Native与ExMobi也都提出了各自的思路。

React Native使用的JSX其实就是一个JS框架,这个框架在Facebook的另一个产品React JS中也是一个基础,应该是属于一个体系中的产品。所以,这一体系中的产品无论Android、iOS还是Web,开发方式都是一样的,只是各自的UI组件不同,每一种平台都要渲染自己的UI组件。

而React JS本身也没有对H5的组件做过多的封装,而是提出了一种全新的UI组件的封装与渲染模式,它与MVV*概念不应相提并论,而是可以跟jQuery、BootStrap等优秀的前端框架一起来使用。

除此之外,React Native也支持webview组件来使用HTML5。所以,从Web到Native,React的整个体系还是相对比较完整的。

ExMobi也有一个HTML5的开发框架伴侣——Agile Lite移动应用前端框架,此框架是一个完整的MVC的框架,而且封装的UI组件与ExMobi的UI组件基本一致,并支持组件的扩展。同时可以在ExMobi的webview组件和微信中智能调用各自的本地能力,而在普通浏览器中则调用浏览器能力。开发者可以很方便的使用框架进行完整webapp的开发而不需要再借助其他的前端框架(当然也可以结合Bootstrap、Ratchet等框架)。而其对微信API的封装也可以提升微信应用的开发效率,基于ExMobi支持的webview组件,使用Agile Lite开发的微信应用也可以方便移植到ExMobi开发的原生app中。

下面是Agile Lite官网提供的示例,开发者可以体验一下:

总结

对于开发者来说现在有越来越多的技术方向的可以选择,移动应用开发也不例外。React Native以其敏锐的技术眼光与ExMobi多年的市场检验结果不谋而合,都坚定的选择了移动应用原生开发的技术路线,并通过各自的技术特点将原生开发的思路扩展到web开发的领域,通过web开发的技巧使开发的APP完全具备原生应用的所有高效、流畅、无限接近系统效果的用户体验。虽然在技术路线上稍有不同,但也给开发者更多的思考空间,相信随着移动物联时代的不断进步,还会涌现出更多新的思维和模式,请让我们一起翘首期待。

   
3000 次浏览       15
相关文章 相关文档 相关课程



深度解析:清理烂代码
如何编写出拥抱变化的代码
重构-使代码更简洁优美
团队项目开发"编码规范"系列文章
重构-改善既有代码的设计
软件重构v2
代码整洁之道
高质量编程规范
基于HTML5客户端、Web端的应用开发
HTML 5+CSS 开发
嵌入式C高质量编程
C++高级编程
最新课程计划
信息架构建模(基于UML+EA)3-21[北京]
软件架构设计师 3-21[北京]
图数据库与知识图谱 3-25[北京]
业务架构设计 4-11[北京]
SysML和EA系统设计与建模 4-22[北京]
DoDAF规范、模型与实例 5-23[北京]

Android手机开发(一)
理解Javascript
非典型ajax实践
彻底的Ajax
javascript 使用Cookies
使用 jQuery 简化 Ajax 开发
更多...   

Struts+Spring+Hibernate
基于J2EE的Web 2.0应用开发
J2EE设计模式和性能调优
Java EE 5企业级架构设计
Java单元测试方法与技术
Java编程方法与技术

某航空公司IT部 JavaScript实践
某电视软件 HTML5和JavaScript
中航信 JavaScript高级应用开发
大庆油田 web界面Ajax开发技术
和利时 使用AJAX进行WEB应用开发
更多...