跨平台开发时代的 (再次) 到来?

这篇文章主要想谈谈最近又刮起的移动开发跨平台之风,并着重介绍和对比一下像是XamarinNativeScriptReact Native和 DeviceOne 之类的东西。不会有特别深刻的技术讨论,你们能够看成一篇科普类的文章来看。javascript

故事的开始

“一次编码,到处运行” 永远是程序员们的理想乡。二十年前 Java 正是举着这面大旗登场,击败了众多竞争对手。可是时至今日,事实已经证实了 Java 笨重的体型和缓慢的发展显然已经很难再抓住这个时代快速跃动的脚步。在新时代的移动大潮下,一个应用想要取胜,完美的使用体验能够说必不可少。使用 native 的方式当然对提高用户体验颇有帮助,可是移动的现状是必须针对不一样平台 (至少是 iOS 和 Android) 进行开发。这对于开发来讲妥妥的是隐患和额外的负担:咱们不只须要在不一样的项目间努力用不一样的语言实现一样代码的同步,还要承担由此带来的后续维护任务。若是仅只限制在 iOS 和 Android 的话还行,可是若是还要继续向 Windows Phone 等平台拓展的话,所须要付出的代价和工数将几何级增加,这显然是难以接受的。因而,一个其实一直断断续续被说起可是从没有占据过统治地位的概念又一次走进了移动开发者们的视野,那就是跨平台开发。css

本地 HTML 和 JavaScript

由于每一个平台都有浏览器,也都有 WebView 控件,因此咱们可使用 HTML,CSS 和 JavaScript 来将 web 的内容和体验搬到本地。经过这样作咱们能够将逻辑和 UI 渲染部分都统一,以减小开发和维护成本。这种方式开发的 app 通常被称为 Hybrid app,像 PhoneGap 或者 Cordova 这样的解决方案就是典型的应用。除了使用前端开发的一套技巧来构建页面和交互之外,通常这类框架还会提供一些访问设备的接口,好比相机和 GPS 等。前端

虽然使用全网页的开发策略和环境能够带来代码维护的便利,可是这种方式是有致命弱点的,那就是缓慢的渲染速度和难以驾驭的动画效果。这二者对于用户体验是致命并且难以接受的。随着三年前 Facebook 使用 native 代码从新构建 Facebook 的手机 app 这一标志性事件的发生,曾经一度占领半壁江山的网页套壳的 app 的发展也日渐式微。特别在如今对于用户体验的追求几近苛刻的如今,呆板的动画效果和生硬的交互体验已经彻底没法知足人民群众对高质量 app 的心理预期了。java

跨平台之心不死的咱们该怎么办

想要解决用户体验的问题,基本仍是须要回到 native 来进行开发,可是这种行为必然会与平台绑定。世界上老是有聪明人的,而且他们总会利用看起来更加聪明可是实际上却很笨的电脑来作那些很笨的事情 (恰得其所)。其中一件事情就是自动将某个平台的代码转换到另外的平台上去。有一家英国的小公司正在作这样的事情,MyAppConverter 想作的事情就是把 iOS 的代码自动转成 Java 的。可是很惋惜,若是你尝试过的话,就知道他们的产品暂时还处于没法实用的状态。node

在这条路的另外一个分叉上有一家公司走得更远,它叫作 Apportable。他们在游戏的转换上已经取得了很大的成果,像是 Kingdom Rush 或者 Mega Run 这样的大做都使用了这家的服务将游戏从 iOS 转换到 Android,而且很是成功。能够绝不夸张地说,Apportable 是除开直接使用像 Unity 或者 Cocos2d-x 之外的另外一套诱人的游戏跨平台解决方案。基本上你可使用 Objective-C 或者 Swift 来在熟悉的平台上开发,而没必要去触碰像是 C++ 这样的怪兽 (虽然其实在游戏开发中也不会碰到很难的 C++)。程序员

可是好消息终结于游戏开发了,由于游戏在不一样平台上体验不会差异很大,也不多用到不一样平台的不一样特性,因此处理起来相对容易。当咱们想开发一个非游戏的 app 时,事情就要复杂得多。虽然 Apportable有一个计划让 app 转换也能可行,可是估计还须要一段时间咱们才能看到它的推出。web

新的但愿

Xamarin

其实跨平台开发最大的问题仍是针对不一样的平台 UI 和体验的不一样。若是忽视掉这个最困难的问题,只是共用逻辑部分的代码的话,问题一会儿就简单很多。十多年前,当 .NET 刚刚被公布,你们对新时代的开发充满期待的同时,一群喜欢捣鼓的 Hacker 就在盘算要如何将 .NET 和 C# 搬到 Linux 上去。而这就是 Mono的起源。Mono 经过在其余平台上实现和 Windows 平台下功能相同的 Common Language Runtime 来运行 .NET 中间代码。如今 Mono 社区已经足够强大,而且不只仅支持 Linux 平台,对移动设备也一样支持。Mono 背后的支撑企业 Xamarin 也瓜熟蒂落并适时地推出了一整套的移动跨平台解决方案。npm

Xamarin 的思路相对简单,那就是使用 C# 来完成全部平台共用的,和平台无关的 app 逻辑部分;而后因为各个平台的 UI 和交互不一样,使用预先由 Xamarin 封装好的 C# API 来访问和操控 native 的控件,进行分别针对不一样平台的 UI 开发。windows

虽然只有逻辑部分实现了真正的跨平台,而表现层已然须要分别开发,但这确实也是一种在完整照顾用户体验的基础上的好方式 -- 至少开发语言获得了统一。由于 Xamarin 解决方案中的纯 C# 环境和有深厚的 .NET 技术背景作支撑,这个项目如今也受到了微软的支持和重视。后端

不过存在的致命问题是针对某个特定平台你所能使用的 API 是由 Xamarin 所决定的。也就是说一旦 iOS 或者 Android 平台推出了新的 SDK,加入了新的功能,你必需要等 Xamarin 的工程师先进行封装,而后才能在本身的项目中使用。这种延迟每每多是致命的,由于如今 AppStore 对于新功能的首页推荐每每只会有新系统上线后的一两周,错过这段时间的话,可能你的 app 就再无翻身之日。并且若是你想使用一些第三方框架的话,将不得不本身动手将它们打包成二进制,而且写 binding 为它们提供 C# 的封装,除非已经有别人帮你作过这件事情了。

另外,由于 UI 部分仍是各自为战,因此不一样的代码库依然存在于项目之中,这对工做量的减小的帮助有限,而且以后的维护中仍是存在没法同步和版本差别的隐患。可是整体来讲,Xamarin 是一个很不错的解决跨平台开发的思路了。(若是抛开价格因素的话)

NativeScript

NativeScript 是一家名叫 Telerik 的名不见经传保加利亚公司刚刚宣布的项目。虽然 Telerik 并非很出名,可是却已经在 hybrid app 和跨平台开发这条路上走了好久。

JavaScript 由于普遍的群众基础和易学易用的语言特色,已经大有一统天下的趋势。而如今主流移动平台也都有强劲的处理 JavaScript 的能力 (iOS 7 之后的 JavaScriptCore 以及 Android 自带的 V8 JavaScript Engine),由于使用 JavaScript 来跨平台水到渠成地成为了一个可选项。

在此要吐槽一下,JavaScript 真的是一家公司,一个项目拯救回来的语言。V8 以前谁能想到 JavaScript 能有今日...

NativeScript 的思路就是使用移动平台的 JavaScript 引擎来进行跨平台开发。逻辑部分天然无需多说,关键在于如何使用平台特性,JavaScript 要怎样才能调用 native 的东西呢。NativeScript 给出的答案是经过反射获得全部平台 API,预编译它们,而后将这些 API 注入到 JavaScript 运行环境,接下来在 Javascript 调用后拦截这个调用,并运行 native 代码。

在此不打算展开说 NativeScript 详细的原理,若是你对它感兴趣,不妨去看看 Telerik 的员工的写的这篇博客以及发布时的 Keynote

这么作最大的好处是你能够任意使用最新的平台 API 以及各类第三方库。经过对元数据的反射和注入,NativeScript 的 JavaScript 运行环境总能找到它们,触发相应的调用以及最终访问到 iOS 或者 Android 的平台代码。最新版本的平台 SDK 或者第三方库的内容老是能够被获取和使用,而不须要有什么限制。

举个简单的例子,好比建立一个文件,为 iOS 开发的话,能够直接在 JavaScript 里写这样的代码:

var fileManager = NSFileManager.defaultManager(); fileManager.createFileAtPathContentsAttributes( path ); 

而对应的 Android 版本也许是:

new java.io.File( path ); 

你不须要担忧 NSFileManager 或者 java.io 这类东西的存在,而是能够任意地使用它们!

若是仅只是这样的话,使用上仍是很是不便。NativeScript 借助相似 node 的一套包管理系统,用 modules 对这些不一样平台的代码进行了统一的封装。好比上面的代码,能够统一使用下面的形式替换:

var fs = require( "file-system" ); var file = new fs.File( path ); 

写过 node 的同窗确定对这样的形式很熟悉了,这里的 file-system 就是 NativeScript 进行的统一平台的封装。如今的完整的封装列表能够参见这个 repo。由于写法很简单,因此开发者若是有须要的话,也能够建立本身的封装,甚至使用 npm 来发布和共享 (固然也有获取别人写的封装)。由于依赖于已有的成熟包管理系统,因此能够认为扩展性是有保证的。

对于 UI 的处理,NativeScript 选择了使用相似 Android 的 XML 的方式进行布局,而后用 CSS 来控制控件的样式。这是一种颇有趣的想法,虽然 UI 的布局灵活性上没法与针对不一样平台的 native 布局相比,可是其实和传统的 Android 布局已经很接近。举个布局文件的例子就可见一斑:

<Page loaded="onPageLoaded"> <GridLayout rows="auto, *"> <StackLayout orientation="horizontal" row="0"> <TextField width="200" text="{{ task }}" hint="Enter a task" id="task" /> <Button text="Add" tap="add"></Button> </StackLayout> <ListView items="{{ tasks }}" row="1"> <ListView.itemTemplate> <Label text="{{ name }}" /> </ListView.itemTemplate> </ListView> </GridLayout></Page> 

熟悉 Android 或者 Window Phone 开发的读者可能会感到找到了组织。你可能已经注意到,相比于 Android 的布局方式,NativeScript 天生支持 MVVM 和 data binding,这在开发中会十分方便 (可是性能上暂时就未知了)。而像是 Button 或者 ListView 这样的控件都是由 modules 映射到对应平台的系统标准控件。这些控件的话都是使用 css 来指定样式的,这与传统的网页开发没太大区别。

NativeScript 表明的思路是使用大量 web 开发的技巧来进行 app 开发。这是一个很值得期待的方向,相信也会受到不少前端开发者的欢迎 -- 由于工具链和语言都很是熟悉。可是这个方向依然面临的最大挑战仍是 UI,如今看来开发者是被限制在预先定义好的 UI 控件中的,而不能像传统 Hybrid app 那样使用 HTML5 的元素。这使得如何能开发出高度自定义的 UI 和交互成为问题。另外一个可能存在的问题是最终 app 的尺寸。由于咱们须要将整个元数据注入到运行环境中,也存在不少在不一样语言中的编译,因此不可避免地会形成较大的 app 尺寸。最后一个挑战是对于像 app 这样的工程,没有类型检查和编译器的帮助,开发起来难度会比较大。另外在调试的时候也可能会有传统 app 开发中未曾遇到的问题。

整体来看,NativeScript 是颇有但愿的一个方案。若是它能实现本身的愿景,那必将是跨平台这块大蛋糕的有力竞争者。固然,如今 NativeScript 还太年轻,也还有不少问题。不妨多给这个项目一点时间,看看正式版本上线后的表现。

React Native

Facebook 几个月前公布了 React Native,而今天这个项目终于在万众期待下发布了。

React Native 在必定程度上和 NativeScript 的概念相似:都是使用 JavaScript 和 native UI 来实现 app (因此说 JavaScript 真是有一桶浆糊的趋势..若是你如今还不会写几句 JavaScript 的话,建议尽早学一学)。可是它们的出发点略有不一样,React Native 在首页上就写明了,使用这个库能够:

learn once, write anywhere

而并非 "run anywhere"。因此说 React Native 想要达成的目标其实并非一个跨平台 app 开发方案,而是让你可以使用类似的方法和一样的语言来在不一样平台进行开发的工具。另外,React Native 的主要工做是构建响应式的 View,其长处在于根据应用所处的状态来决定 View 的表现状态。而对于其余一些系统平台的 API 来讲,就显得比较无力。而正是因为这些要素,使得 React Native 确实不是一个跨平台的好选择。

那为何咱们还要在这篇以 “跨平台” 为主题的文章里谈及 React Native 呢?

由于虽然 Facebook 不是以跨平台为出发点,可是却不可能阻止工程师想要这么来使用它。从原理上来讲,React Native 继承了 React.js 的虚拟 DOM 的思想,只不过此次变成了虚拟 View。事实上这个框架提供了一组 native 实现的 view (在 iOS 平台上是 RCT 开头的一系列类)。咱们在写 JavaScript (更准确地说,对于 React Native,咱们写的是带有 XML 的 JavaScript:JSX) 时,经过将虚拟 View 添加并绑定到注册的模块中,在 native 侧用 JavaScript 运行环境 (对于 iOS 来讲也就是 JavaScriptCore) 执行编译并注入好的 JavaScript 代码,获取其对 UI 的调用,将其截取并桥接到 native 代码中进行对应部件的渲染。而在布局方面,依然是经过 CSS 来实现的。

这里整个过程和思路与 NativeScript 有类似之处,可是在与 native 桥接的时候采起的策略彻底相反。React Native 是将 native 侧做为渲染的后端,去提供统一的 JavaScript 侧所须要的 View 的实体。NativeScript 基本算反其道行之,是在 JavaScript 里写分开的中间层来分别对应不一样平台。

对于非 View 的处理,对于 iOS,React Native 提供了 RCTBridgeModule 协议,咱们能够经过在 native 侧实现这个协议来提供 JavaScript 中的访问可能。另外,回调和事件发送等也能够经过相应的 native 代码来完成。

总结来讲,若是想要把 React Native 做为一个跨平台方案来看的话 (实际上也并不该当如此),那么单靠 JavaScript 一侧是难以完成的,由于一款有意义的 app 不太可能彻底不借助平台 API 的力量。可是毕竟这个项目背后是 Facebook,若是 Facebook 想要经过本身的影响力自立一派的话,一定会经过不断改进和工具链的完善,将 app 开发的风向引导至本身旗下。对于原来就使用 React.js 的开发者来讲,这个框架下降了他们进入 app 开发的门槛。可是对于已经在作 native app 开发的人来讲,是否值得和须要投入精力进行学习,还须要观察 Facebook 接下来动做。

不过如今 React Native 的正式发布才过去了不到 24 小时,我想咱们有的是时间来思考和检阅这样一个框架。

DeviceOne

杯子科技 大约两个月左右公布了 DeviceOne。

DeviceOne 一个全新的模式:打破了以前的全部模式,实现了整个都是 native UI 来实现 app 。可是它们的出发点略有不一样,DeviceOne 在首页上就写明了,使用这个平台能够:

write once, run anywhere

而并非 "learn once, write anywhere"。因此说DeviceOne  想要达成的目标实际上是一个全新跨平台 app 开发方案,让你可以使用一样的语言来开发在不一样平台的工具。而对于其余一些系统平台的 API 来讲,就显得比较无力。而正是因为这些要素,使得 DeviceOne 确实是一个跨平台的好选择。

使用JSON描述UI,可是有本身的IDE能够可视化拖拽UI组件,能够在IDE上设置UI的属性。

* 使用Javascript或者lua来描述逻辑,经过运行时javascript引擎和lua引擎来加载原生API。

* 一套规范来实现原生组件的扩展,目前已经有大概70个跨平台的组件,包括最基础的button,label,也包括复杂的UI页面组件,也包括不少第三方的组件百度推送,地图之类的。组件扩展的方式已经开放给原生开发人员,除了咱们本身一直在开发新组件,他们也能够开发本身的组件加载到咱们的平台上,并且能够分享到咱们的组件商店给其余人用。

* 支持动态选择组件打包,核心很小,用户能够另外勾选这70个组件上任何一些组件组合打包成ipa,apk,appx

* 支持Android4.0以上,IOS7.0以上,windows8.1以上,winphone8.1以上。

* 自动适配机型分辨率,用户无需再考虑适配问题。

 

总结

固然还有一些其余方案,好比 Titanium 等。如今使用跨平台方案开发 app 的案例并不算不少,可是不管在项目管理仍是维护上,跨平台始终是一种诱惑。它们都解决了一些 Hybrid app 的遗留问题,可是它们又都有一些非 native app 的广泛面临的阴影。谁能找到一个好的方式来解决像是自定义 UI,API 扩展性以及 app 尺寸这样的问题,谁就将能在这个市场中取得领先或者胜利,从而引导以后的开发潮流。

可是谁又知道最后谁能取胜呢?也有可能你们在跨平台的道路上再一次全体失败。乘机而动也许是如今开发者们很好的选择,不过个人建议是提早学点儿 JavaScript 老是不会出错的。

相关文章
相关标签/搜索