【Hybrid App】关于Hybrid App技术解决方案的选择

 

【引言】近年来随着移动设备类型的变多,操做系统的变多,用户需求的增长,对于每一个项目启动前,你们都会考虑到的成本,团队成员,技术成熟度,时间,项目需求等一堆的因素。所以,开发App的方案已经变得愈来愈多了。曾经有一段HTML5的小浪潮,无数的人参与或者看到过一个讨论:原生开发仍是混合开发,又或者是Web开发?到底最佳实践是怎样的,笔者认为只有实践过的人才会知道。尤为是在这个充满各类变数的移动互联网时代。javascript

【摘要】笔者将从Hybrid App的开发现状出发,阐述Hybrid App的优缺点,同时对比Hybrid AppNative App的各自特性,最后探讨一下Hybrid App的新思想方向。css

 

Hybrid App现状分析

Web App

毫无疑问Web App就是成本最低,最快速地解决方案了。尤为是近两年很是流行的响应式设计,Web App市场提供了很是好的实践场地。最近典型的Web App最佳案例是Sun天气应用了,其细节处理让人赞不绝口。html

 

通常来讲,拥有下面特色的就是一个Web App了:使用浏览器运行;纯Web前端架构,不少重要手机特性没法访问,例如联系人以及Push notification之类的;Single Page App;销售渠道多限于浏览器。jquery

Hybrid App

所谓的Hybrid App其实会有不一样的分支。并且会和Native应用有重合的地方。下面就说三种不一样的解决方案。git

方案一:使用PhoneGapAppCan之类的中间件,以WebView做为用户界面层,以Javascript做为基本逻辑,以及和中间件通信,再由中间件访问底层API的方式,进行应用开发。这种架构通常会很是依赖WebView层的性能。angularjs

 

方案二:使用Adobe Air、RubyMotion、Appcelerator或者是Xamarin这种非官方语言的工具,打包成原生应用的方式开发。为何笔者会将它们定义为Hybrid App,主要是它们并无很单纯地使用原生提供的语言进行开发,而是经过对开发者提供友好的开发工具,并折中地把这种开发语言转换成原生语言,最终打包出整个应用,因此也属于混合应用范畴。github

方案三:在开发原生应用的基础上,嵌入WebView可是总体的架构使用原生应用提供,通常这样的开发由Native开发人员和Web前端开发人员组成。Native开发人员会写好基本的架构以及API让Web开发人员开发界面以及大部分的渲染。保证到交互设计,以及开发都有一个比较折中的效果出来,优化得好也会有很棒的效果。(当年Facebook Three20就使用该方案)ajax

所以,Hybrid App有如下的特性:

  1. 开发时可能不采用或者大部分不采用原生语言,可是却有全部原生应用的特性;
  2. 架构方案会和原生有出入,基本由工具而定;
  3. 具备跨平台特性;
  4. 通常开发相对原生开发的方式要简单。

Native App

Native App毫无疑问是最可靠的方案。可是学习成本,人才成本,开发效率以及照顾不一样平台的特性去考虑,都成为了开发人员心目中的一道坎。至于说这道坎是不可逾越的仍是一道让你提升的坎,笔者以为彻底取决于你本身。基于种种因素的考虑,估计不少人就会选择折中的方案到了Hybrid App的开发行列当中,包括笔者本身也是这样过来的。

下面更多的内容都将围绕Hybrid App开发展开讨论。

Hybrid App在开发当中的优势和缺点

在Hybrid App的开发过程当中,几种不一样的方案笔者都有经历过。固然也经历到了Native App的开发阶段。在如此纠结复杂的过程当中给了笔者很多的经验,下面笔者也会就自身的经验和你们分享这些方案当中的优缺点。对于初入行的朋友,笔者是从Web前端入行的,毕竟门槛较低,并且可以快速地培养本身的信心以及对代码的感受。深刻后就开始接触到移动开发这块了。因此会先从Hybrid App的第一种方案提及吧。

方案一(Web架构为重)

优势:

  1. 全Web开发,必定程度上有利于Web前端技术人员快速地构建页面样式;
  2. 有利于在不一样的平台上面展现同一个交互层;
  3. 便于调试,开发的时候能够经过浏览器的方式进行调试,工具丰富。

缺点:

  1. 虽说你能够专一在界面以及交互开发上了,可是这页会成为一个缺点,好比说要仿造一个iOS的默认设置界面,就须要大量的html以及css代码了,并且效果不必定和iPhone上面的界面同样好;
  2. 正由于这是跨平台的开发,因此仍是这句话:兼容是前端的痛。了解过在Android机器上面的Web开发就知道这个痛了。好比前些年在Android设备上面写圆角,border-radius:10px,在Android的设备上面会出现毛边。
  3. 便于调试实际上是在Web界面层的。可是实际上作Hybrid App开发的时候,你会遇到需求,进入手机的底层请求,作某些处理。好比说若是该应用有Push Notification服务的话,你就须要到底层,获取Push Notification发生时的数据,以及作相应的交互处理。固然相似PhoneGap这类框架,已经有很好的插件机制去帮助你解决相似的问题,固然还有Game Center之类的插件,具体的话能够到Github去关注PhoneGap官方的帐户,资源很是丰富;

方案二(编译转换方式)

优势:

  1. 利用本身熟悉的语言,进行应用开发,好比RubyMotion,就是使用Ruby语言去作iOS开发,开发起来的话,代码量是数量级地降低啊。
  2. 部分开发工具提供跨平台的功能,让你的应用可以快速地发布到不一样的平台上面。好比Mono社区的Xamarin,就是典型的例子了。使用C#语言,可以把你的应用发布到iOS,Android以及WinPhone市场上面;
  3. 开发出来的程序运行高效。大部分这种架构的应用,其实仍是很是依赖底层的东西的,并且包括界面的东西,都是使用原生的API,效率就固然要比相似于PhoneGap这种架构要好了;

缺点:

严重依赖于其工具厂商提供的工具包,调试的时候就要有全套的工具。固然通常来讲这些厂商都会以收费的形式发布他们的工具,相应的也有客服提供技术支持。遇到系统升级,第三方sdk升级,开发工具出现bug等,那么就要等待工具厂商解决了。至关于把风险压在对方身上了,本身却要承担责任。

方案三(Native架构为重)

优势:

  1. 这无疑是最稳定的Hybrid App开发方式了,交互层的效率上由Native的东西解决了,并且架构上基本就是在App内写网页,连App Store都是采用了该种方案;
  2. 开发时分工很是明确,底层的由iOS开发人员处理,上层的由Web前端开发人员处理;
  3. 有效的在线参数配置方式,以便于及时在线替换界面;

缺点:

  1. 团队至少须要两个工程师,一个是Web的,一个是iOS的。固然若是开发人员会两种技术也可独立承担;
  2. 仍是运行效率,要权衡好多少界面采用Web来渲染,毕竟WebView的效率会相对下降,之前Facebook就是由于Web的渲染效率低下,把整个应用改成原生的解决方案。固然这里面能够经过优化来解决。可是优化也是有限度的,如Ruby创始人Matz所说优化要恰当(包括花的时间,技巧等),并且有时候的优化达到的回报率不必定达到你本身的指望。

Hybrid App和Native App开发对比

由于方案三中的思想基本上就是原生应用的开发思想了。这里要作的对比应该不算大,所以笔者不会作太多的阐述介绍二者的不一样。可是若是是偏重Web架构的,或者是以方案二这种透过特殊工具开发的,就和原生开发有对比了。此次笔者暂时会以方案一拿来讨论。讨论中主要会以架构,代码管理上来讨论,固然也会说到部分细节。

架构讨论:

由于这是偏重于Web开发的应用,这里面就须要开发人员有很强烈的大型Web前端架构思想在里面。提到这里可能立刻浮如今你脑海中的词语就是:angular.js,require.js,sea.js,backbone.js等。没错,这些工具都可以帮助你快速地梳理好思路,管理好你的Web应用。对开发者最友好的,发挥空间最大的非PhoneGap莫属了。因此笔者就会以PhoneGap应用展开讨论。(由于相似Sencha也有提供方案,可是Sencha自己是一个重量级的框架,并且有本身的思想在里头,加上他自己也提供开发工具,在这里就不适合讨论了。对于开发者来讲能够根据本身的需求选择好工具)

从工具上看:

Angular.js

用于双向绑定,网络请求,视图管理等工做。

Require.js

javascript模块化工具,在使用较多的交互对象,PhoneGap插件的时候,你就会发现一个强大的模块化工具会在开发的时候提供极好的帮助。可以帮助你把总体的代码,管理得层次分明。

Jade Template Engine

模板引擎。笔者我的比较推荐使用Jade,并且笔者本人也在博客中屡次写到Jade在不一样场景下使用的技巧的有关文章。主要是jade的语法太简洁了,并且面向JS开发人员很是友好。若是你尚未开始使用模板引擎,赶忙加入这个队列吧,你已经落后了。

Jquery Mobile

若是你暂时尚未一个设计师,可是又急于构造一个应用出来。jquery mobile就提供了多套不一样风格的模板,供你使用,并且还含有不一样的交互动画等。并且也是跨平台的。固然实际场景中,笔者以为你会花不少时间在写css上面,由于设计老是天马行空的。固然你还有不少工具啦,例如sass,以及less.js等。

PhoneGap.js或者Cordova.js

作Phonegap开发必须使用的代码库,用于和PhoneGap框架通信。如今这个库已经更名了,是Cordova。具体为何更名,得问Adobe咯。

PhoneGap Plugins

PhoneGap的插件可以帮助你快速地抵达手机的其余API上面,直接使用Javascript来操控这些底层的API。例如调用Push Notification的相应发生的事件。

从代码目录上面看混合应用中的Web层:

 /js
          mainView.js
          settingView.js
          networkObject.js
          renderObject.js

     /lib
          /PhoneGapPlugins
               push-notification-plugin.js
               pickerView.js
          PhoneGap.js
          zepto.js
          jquerymobile.js
          iscroll.js
          angular.js
          jade.js

     /css
          /mainView
               listItemTemplate.css
               questionListTemplate.css
          /settingView
          /personView
          /layout
               navigationBar.css
               tabButton.css
          app.css

     /template
          /mainView
               listItemTemplate.txt
               questionListTemplate.txt
          /settingView
          /personView
          /layout
               navigationBarTemplate.txt
               tabButtonTemplate.txt

     index.html
     app.js
     require.js

从代码的目录上面看,就是经典的静态网页文件的目录,很是简单。下面就用一句话来讲说整个应用的运做过程吧:

打开PhoneGap应用 ->进入 index.html ->运行require.js ->加载应用资源 -> app.js 控制整个应用 -> angular.js 进行事件绑定以及视图渲染 ->视图渲染的时候会将数据和加载好的视图模板(template目录下的代码)处理 ->通过jade模板引擎 ->渲染到相应的位置上

就是如此简单。

看完了简单的PhoneGap应用后,笔者们来看看简单iOS应用在开发时候的代码目录吧。思路上仍是很是类似的。在这里面,笔者不会深刻代码部分去讨论具体的实现以及细节上的东西。

 demoApp
          /Resource
               navigationBar.png
               navigationBar@2x.png 
         /demoApp
               AppDelegate.h
               AppDelegate.m
               /SettingViewController
                    settingViewController.h
                    settingViewController.m
               /MainViewController
                    mainViewController.h
                    mainViewController.m
               /Supporting Files
                    demoApp-Info.plist
                    InfoPlist.strings
                    ...
          /plugin
               /AFNetworking
                    AFHTTPClient.h
                    AFHTTPClient.m
                    AFHTTPRequestOperation.h
                    AFHTTPRequestOperation.m
                    ...
          /Frameworks
               CoreData.framework
               UIKit.framework
          /Products
               demoApp.app

Objective-C 是一种通用、高级、面向对象的编程语言。Objective-C是承自Smalltalk的信息传递模型(message passing)。Objective-C里,与其说对象互相调用方法,不如说对象之间互相传递信息更为精确。Objective-C强调面对对象编程,且Objective-C中强制要求将类的(interface)与实现(implementation)分为两个部分。类的定义文件遵循C语言之惯例以 .h 为后缀,实现文件以 .m 为后缀。因此你会看到大量的类文件在里头,整个工程就是有不一样的类构成的。(固然可能这么描述不太准确,可是便于你们理解)

这就和丰富的Web前端有很大区别了,在Web前端开发里有HTML,CSS,JS三剑客,必需要用好这三个东西才能够把整个应用才可构建出来。可是在Native应用中,就很单一了。你只须要把握好Objective-C就能够了。所以对于原生应用来讲,开发时只要遵照好规范,即便是一个新手参与开发,也能够快速地上手,看懂代码。由于模式已经定好,你们使用同一套的API。按着流程走就行了。固然学习Objective-C须要过程,可是对于拥有C语言,Java语言经验的开发者来讲,是很是简单的事情。

固然,原生开发的缺点也很明显了,就是知足不了你的跨平台需求。

从代码目录上面看,其实也基本上看到笔者为何使用多种JS库以及框架的缘由了。主要的目的就是为了构建一个可维护的,具备规范性的Web应用。由于自己Javascript这门语言很是灵活,100我的能够具备100种风格,加上没有专门对于Javascript开设的课程,在过往都容易存在对这门语言的误解。基于种种的缘由,就要约束好一个应用的代码风格,架构。此外,Javascript自己没有类的概念,因此在Javascript的面向对象编程中:Javascript的数据和成员封装很简单。没有类,彻底是对象操做。这和Objective-C有很大不一样。这个时候必需要有一种心态处理好整个Web应用:就是尽量地抽象成对象,你的工做就是对象与对象之间存在交流。

另外有一些点是值得开发者注意的。对于原生应用来讲,无论是iOS的,仍是Android的,都会提供一套原生界面的库。以Objective-C为例子。若是笔者须要调用Alert,笔者只须要编写:UIAlertView * alertView = [[UIAlertViewalloc]init];,就把这个view声明好了。再去执行相应的方法,就能够了。可是对于Web应用来讲,就须要编写<div id='alertView'><button>肯定</button></div><script>$('#alertView').show();</script>

,一堆的css代码和html代码去实现。固然你会询问笔者,直接写 alert() 不就能够了吗?要是真这么简单的话,建议你在iOS的WebView中编写一下alert,实现:title 是提示,内容是:alert view,肯定按钮的文字是:好的。你就知道WebView的限制在哪里了。

所以要完成JS在Web App开发当中的最佳实践,确定要学习优秀的思想和实现方法了。在这篇文章里面,笔者们暂时先不去作这种深刻的讨论。而是先把例子抛给你们,也许会在下一次讨论的时候,再详细深刻如下这两个项目。

第一个是斯坦福的iOS开发公开课中的例子,使用objective-c实现,一个简单的卡牌游戏。这是经典的mvc开发了。项目地址以下:https://github.com/lbj96347/Stanford-W2013-CardGame,若是您正在使用Mac,那恭喜你,能够立刻编译这个游戏进行测试以及代码浏览。

第二个是使用JavaScript编写的例子,实现一样的需求,作一个简单的卡牌游戏。可是使用的是HTML+CSS+JS开发。一样学习了继承以及mvc的思想。项目地址是:https://github.com/lbj96347/JSMatchismo ,再次恭喜你,无论使用什么电脑,均可以随时浏览代码以及运行该游戏。

Hybrid App的新思想

这两年多以来,由于市场的不一样,也出现了不同的需求,各个技术都有了新的发展。对于Hybrid App来讲,其实都有了一些新的解决方案。为了解决问题其实最终思想都会被还原成如下几个点上:

  1. 根据需求,选择工具;
  2. 用适当的工具作适当的事情,有针对性地解决问题;
  3. 世界是平衡的,对于开发者来讲,作的有用功越多,用户体验就越好,反之越差;
  4. 跨平台是一个"幌子",什么都作获得不表明什么都作得好

这也是笔者体验最深的几个点。并且你会发现Hybrid技术也基本在跟随这几个点来走。

根据需求,选择工具

若是你使用过Jquery Mobile,你作过过场动画(就是从一个view去到另外一个view),过场动画在iOS的navigationController中很常见,并且很简单,效果很好很流畅。在Jquery Mobile中使用ajax,css去实现了,核心代码可能就几十行。可能跟iOS里面的差很少(若是包含动画),可是实际出来的效果却差强人意。会出现相似的问题:页面抖动,感受不连贯,在部分的设备下运行缓慢。若是你的应用要求的体验并非很高,例如一些新闻展现类应用,更强调排版。这里小小的体验差距,就能够忽略了。(由于英国BBC就是这么干的),可是若是你的应用很是强调体验细节,这里的解决方案可能就不适合了。或许你要作优化,可是优化的时间可能足以够你去学习更多的东西了。这样的话,你是继续选择用一个不成熟的工具,仍是选择去学习一种新的语言呢?因此仍是根据需求而定吧。

另一个例子。曾经有人跟笔者说起到,在使用HTML和CSS编写应用界面时确实很爽,可是效率不咋的。那为何不尝试把应用内容直接搬到Canvas里面呢?构造一套足够强大的工具,一套足够彪悍的UI组件,把整个应用运行于Canvas中。这种想法是很好的,可是其实里面的短板页就出现了,Canvas的性能虽高,可是里面的元素组件多了你能够保证效果高?全部的东西都会依赖于JavaScript,这对于Javascript来讲要构造足够强悍的面向对象的组件,也非简单之事,抛弃了CSS和HTML,意味着内部的设计组件可以高度定制,松耦合作得很是好。彻底是实现了一套新的xcode和ui库啊。这就不是在解决一两个问题了。既然有这么一个工具,笔者为何不选择更好的,例如Xamarin。

用适当的工具作适当的事情

作游戏的朋友估计就深有体会了。为了解决Canvas性能的问题,愈来愈多的人和应用厂商(尤为是浏览器厂商),提供一种解决方案就是但愿将Canvas API和系统底层的API打通。意味着你只须要编写Canvas代码,实际作渲染的时候使用的是系统底层的东西,总体上提升了性能。例如Ejectahttp://impactjs.com/ejecta 这个东西。

对于开发人员来讲用Javascript编写游戏逻辑以及作各类控制都很是舒服,并且由于用的API相同,放到PC上(放开性能问题),一样能够运行。这就真的作到了跨平台,可是又不缺少效率。让笔者感触最深的就是@大城小胖在作混合应用(作游戏)时的作法,小胖的游戏架构。JS负责逻辑,引擎。JS Binding绑定原生OpenGL,让原生的来作复杂的渲染处理。HTML CSS能够处理UI(好比一些Button)。这就是典型的:让工具去作其擅长的事情。

跨平台是一个"幌子"

为何这么说?笔者不是一直但愿你们可以跨平台么?是的。可是要真的认清这个坎。从IE兼容,到目前多个浏览器的乱战,到iOS以及Android设备Web上的兼容,这不就是一个历史的例子嘛。跨平台不是很差,只是在一个时代里,你可以达到怎样的效果,真的是很难估量的。就比如你出国旅游,若是两国关系很是好,并且不少惯例法律一致,对你来讲不会形成太多负担。可是若是语言不同,生活习惯什么的都不一样,你就很难适应。一样是人,你很难在不一样的环境下生存。真正的跨平台,就意味着你们求同。这绝对不是一两天的事情,也非简单的事情。

那为何还要跨平台。业务需求嘛。在这里必须就要遵照根据需求选择工具,用适当的工具作适当的事情,根据实际状况来做开发。若是能够,笔者以为颇有必要都了解一遍,这样的话各类开发的思想就会影响到你,你就可以分辨到什么是好什么是坏,作更好的选择。例如笔者刚刚说到的过场动画的例子。其实彻底可使用笔者说的混合应用中,方案三,去解决这个问题。你无非就是但愿用navigationController作一个漂亮的过场动画嘛,在iOS中几句代码就实现了。

再说一个例子吧,若是你正在作一个todo-list的应用,其实无非就是简单存储数据以及作一些相关界面渲染。在使用原生的控件的话,有大堆的代码要写,并且还要处理好内存问题。可是其实若是使用Web的方式实现,好比backbone.js。整体代码可能100行左右。就把整个应用实现了,包括本地存储。你要作的事情就是把整个界面搭建得漂亮些。可能就1个小时的工做。可是若是用原生开发,很难保证到一个小时内完成,由于调试编译都须要时间吧?何况还有界面呢。

因此要认清跨平台这个"幌子",并不是全部的问题都用同一个方法处理。笔者们要融汇贯通嘛!

总结和笔者的感觉

对于作Web App的坑,其实挺多的。这里没法一一表达。可是相信实践过就会知道如何更好地绕过这些坑(例如笔者说的过场动画的例子)。那么对于开发者来讲要有坚强的毅力,努力去实践,知足本身永远不能知足的好奇心,由于最终的经验会给你带来不同的感觉,stay hungry。同时笔者们必须保持一颗学习的心,不断地吸取有养分的思想,学习新的知识,不要太容易知足,stay foolish。每一种语言都会有其中的思想,每一种工具都有本身解决问题的方法论。多尝试就可以给本身带来更优秀的架构,更优秀的应用,提供给用户更好的体验。固然,也会有更好的回报。

关于做者

李秉骏(@CashLee李秉骏),HTML5技术活跃分子,HTML5梦工场高级成员,投入Web开发多年。高中开始编写独立运营的电子商务网站。近年多进行移动应用先后端的开发,并尝试将混合应用开发技术运用于实践当中。

http://www.infoq.com/cn/articles/hybrid-app-development-combat