让自己开发的软件能够跨平台运行,既是每个软件开发者多年以来的梦想,也是许多软件开发者的噩梦。到今天为止,软件界在跨平台开发、运行应用程序方面已经取得了很大的进展,但离理想的目标还有很远的路要走。
当我们谈论"跨平台开发“、"跨平台运行“、"跨平台发布“等等之类的话题时,所提到的“平台”是指各类操作系统级别的平台,既包括PC操作系统,如windows、mac os、linux,也包括移动设备操作系统(如苹果IOS,谷歌Android);"跨平台应用程序开发"则是指“开发可以运行在多个操作系统上的应用程序”,就如上面提到那些操作系统。
在软件业早期,跨平台开发是比较麻烦的。早期的软件开发语言大多是编译型的,且编译出来的代码(BinaryCode)与操作系统密切相关,所以是无法跨平台运行的。
那么,编译型语言就没法跨平台了吗?当然是有办法的,既然在BinaryCode层次无法实现跨平台,那就在源代码(SourceCode)层次实现跨平台。
以c/c++语言为例,在不同的操作系统上,均有相应的编译器,开发人员在开发相应软件时,根据编译器中定义的预编译宏,对于代码中的部分系统API调用代码单独编写,然后通让特定平台的编译器去编译对应的代码。
听起来似乎一切都不错,只需要改少量源代码,然后用目标系统进行编译即可运行,事情真的这么简单吗?
对于用编译型语言开发的软件来说,如果软件是没有图形界面(GUI)的话,源代码改动工作量的确不大;但如果涉及GUI界面,问题就会比较复杂。当然,也有办法:不要使用与操作系统绑定的GUI接口或框架,例如windows下的MFC库;你应该使用一个跨平台的GUI库,例如QT,GTK。
需要注意几点:
#ifdef _WIN32
//define something for Windows (32-bit and 64-bit, this part is common)
#ifdef _WIN64
//define something for Windows (64-bit only)
#else
//define something for Windows (32-bit only)
#endif
#elif __APPLE__
#include "TargetConditionals.h"
#if TARGET_IPHONE_SIMULATOR
// iOS Simulator
#elif TARGET_OS_IPHONE
// iOS device
#elif TARGET_OS_MAC
// Other kinds of Mac OS
#else
# error "Unknown Apple platform"
#endif
#elif __ANDROID__
// android
#elif __linux__
// linux
#elif __unix__ // all unices not caught above
// Unix
#elif defined(_POSIX_VERSION)
// POSIX
#else
# error "Unknown compiler"
#endif
解释型编程语言有良好的平台兼容性,它一边解释一边运行,在任何环境中都可以运行–前提是安装了解释器。灵活,修改代码的时候直接修改就可以,可以快速部署,不用停机维护。
解释型编程语言通常也是动态类型编程语言:
动态类型语言是指在运行期间才去做数据类型检查的语言,也就是说,在用动态类型的语言编程时,永远也不用给任何变量指定数据类型,该语言会在你第一次赋值给变量时在内部将数据类型记录下来,并且在你再次更改值类型时自动更改数据类型–换句说,变量类型是值类型决定的。
例如:php、python、Ruby等,这些语言在设计之初就考虑了在PC操作系统上的运行问题,分别为不同操作系统设计了对应的解释器,因此它们能够实现“写一份代码,在多个操作系统上运行“–移动端系统除外(IOS和Android等)。
典型代表语言:Java。
为什么说它是伪编译型呢?因为,用Java开发的代码,会编译成一个字节码的文件,它能够在安装Java虚拟机的操作系统上被执行,在执行字节码时则是解释执行。
如上所述,Java程序通过虚拟机实现跨平台运行(GUI程序 、非GUI程序均可),但仅能跨PC操作系统平台,无法同时跨移动平台。虽然Java语言同时是Android系统上的原生开发语言,但Android和PC操作系统的Java代码也只能实现部分兼容(比如一些通用的无界面的代码)。
现在主流浏览器都已经全面支持、兼容W3C标准,因此只要我们的软件集成支持原生编程语言上的浏览器内核,就可以正常运行基于W3C标准(HTML+CSS+JavaScript)开发的网页。
万维网联盟(英语缩写:W3C)标准不是某一个标准,而是一系列标准的集合。网页主要由三部分组成:结构(Structure)、表现(Presentation)和行为(Behavior)。
HTML、XHTML属于结构标准语言;
层叠样式表(英语缩写:CSS)属于表现标准语言;
文档档对象模型(英语缩写:DOM)和JJavaScript属于行为标准语言。
在软件中集成一个浏览器内核,运行基于网页开发的应用程序的基本步骤如下:
大多数编程语言厂商提供浏览器内核组件,以WebView、WebBrowser形式出现。
当然,你也可以引入第三方组件来处理。
但是WebView、WebBrowser是一个很重的控件,很容易产生内存问题,而且复杂的UI在WebView上显示的性能不好。JS与Native代码之间的通信需要使用JSBridge进行上下文切换,因此会降低一些性能。
按照上述方法虽然大大简化了跨平台开发的难度,但还是比较繁琐(实质是在开发一个小的跨平台开发框架),而且用户体验、性能也是问题,对于一般的开发者来说,要对浏览器内核进行优化是一个很大的挑战;那有没有更好的解决办法?
答案是:有办法,已经有许多现成的框架我们可以直接使用而无需从头造轮子。
Cordova 是Apache旗下的一个开源的移动开发框架。它允许你使用WEB开发技术(HTML5、CSS3、JavaScript)进行跨平台开发。应用在每个平台的封装器中执行,并且依赖规范的API对设备进行高效的访问,比如传感器、数据、网络状态等等。
Cordova通过对HTML、CSS、JS封装为原生APP。Cordova将不同设备的功能,按标准进行了统一封装,开发人员不需要了解设备的原生实现细节,并且提供了一组统一的JavaScript类库,以及为这些类库所使用的设备相关的原生后台代码。因此实现了“write once, run anywhere”(一次开发,随处运行)。
跨平台能力
Cordova几乎支持所有主流的PC(linux、windows、mac)、移动操作系统(Ios、Android),是支持跨平台运行最全的一个框架,如果是想在最短的时间里支持尽可能多的平台,那Cordova是最优先且正确的选择。
Electron 基于 Chromium 和 Node.js, 让你可以使用 HTML, CSS 和 JavaScript 构建应用。
如果你可以建一个网站,你就可以建一个桌面应用程序。
Electron 是一个使用 JavaScript, HTML 和 CSS 等 Web 技术创建原生程序的框架,它负责比较难搞的部分,你只需把精力放在你的应用的核心上即可。Electron 兼容 Mac、Windows 和 Linux,可以构建出三个平台的应用程序。
更妙的是,Cordova和Electron可以结合起来。最新版本的Cordova已经集成了Electron,可以直接用Cordova构建Electron程序。
跨平台能力
Electron本身只能支持Mac、Windows 和 Linux平台开发,不能支持移动端开发。
Weex 是使用流行的 Web 开发体验来开发高性能原生应用的框架。
“Weex” 的发音是 /wiːks/, 和 “Weeks” 同音。
Weex 致力于使开发者能基于通用跨平台的 Web 开发语言和开发经验,来构建 Android、iOS 和 Web 应用。简单来说,在集成了 WeexSDK 之后,你可以使用 JavaScript 语言和前端开发经验来开发移动应用。
Weex 渲染引擎与 DSL 语法层是分开的,Weex 并不强依赖任何特定的前端框架。目前 Vue.js 和 Rax 这两个前端框架被广泛应用于 Weex 页面开发,同时 Weex 也对这两个前端框架提供了最完善的支持。Weex 的另一个主要目标是跟进流行的 Web 开发技术并将其和原生开发的技术结合,实现开发效率和运行性能的高度统一。在开发阶段,一个 Weex 页面就像开发普通网页一样;在运行时,Weex 页面又充分利用了各种操作系统的原生组件和能力。
跨平台能力
Weex只能支持Android、iOS跨平台开发。
uni-app是一个使用Vue.js 开发网页应用的框架。
uni-app官方号称支持8个平台,但从操作系统级别来说,只支持iOS、Android平台。其他所谓平台,是指各类应用软件上的小程序,这也算是平台,只不过是应用级平台。
跨平台能力
uni-app只能支持Android、iOS跨平台开发。
React Native技术抛开了WebView,利用JavaScriptCore来做桥接,将JS调用转为native调用,只牺牲了小部分性能获取的跨平台开发,这是一大步进步。但是由于依然存在一个从JS代码到原生代码的转化过程,在界面UI被频繁操作的情况下,可能会导致性能问题.
React Native使你只使用JavaScript也能编写原生移动应用。 它在设计原理上和React一致,通过声明式的组件机制来搭建丰富多彩的用户界面。
React Native产出的并不是“网页应用”, 或者说“HTML5应用”,又或者“混合应用”。 最终产品是一个真正的移动应用,从使用感受上和用Objective-C或Java编写的应用相比几乎是无法区分的。 React Native所使用的基础UI组件和原生应用完全一致。 你要做的就是把这些基础组件使用JavaScript和React的方式组合起来。
React Native完美兼容使用Objective-C、Java或是Swift编写的组件。 如果你需要针对应用的某一部分特别优化,中途换用原生代码编写也很容易。 想要应用的一部分用原生,一部分用React Native也完全没问题 —— Facebook的应用就是这么做的。
跨平台能力
React Native支持Android、iOS跨平台开发,社区也开发出了针对其他平台的项目,但这些要么是实验性的,要么已经不再有人维护,不建议使用它们。
Flutter是一款移动应用程序SDK,一份代码可以同时生成iOS和Android两个高性能、高保真的应用程序。
Flutter目标是使开发人员能够交付在不同平台上都感觉自然流畅的高性能应用程序。
Flutter包括一个现代的响应式框架、一个2D渲染引擎、现成的widget和开发工具。
Flutter目标是使开发人员能够交付在不同平台上都感觉自然流畅的高性能应用程序是用Dart语言编写的,如果使用过Java或JavaScript之类的语言,则该应用程序看起来很熟悉。 使用面向对象语言的经验绝对有帮助,但一些Flutter应用程序甚至是没有编程经验的人写的!
使用Flutter的好处:
跨平台能力
Flutter只能支持Android、iOS跨平台开发。
上面介绍了这么多跨平台开发实现的方法,应该如何选择何种方案呢?
我们要知道,任何技术方案都不是完美的,需要在时间、进度、成本、技术风险、人员能力上综合考虑,选择适合自己的解决方案,“满足业务需要,适当考虑可扩展性和先进性”应该是我们进行技术选型的基本原则。
当然,如果你有一颗伟大的梦想、立志改变世界,那就直接创造一个全新的框架和语言,让开发者都用你的作品进行开发,那真的是太酷了!加油!
访问最新文章,请访问我的独立博客或者关注微信公众号:
独立博客: http://gch.w3c0.com/
微信公众号:程序与算法