混合开发实践

混合开发使用场景

移动混合开发不是新概念了。移动应用可分为三类,一是原生应用,一是web应用,介于这两者之间的是混合应用。每一种技术方案都有它的使用场景。盲目的使用显然会导致产品质量的低下。

毫无疑问,原生应用的性能和用户体验都要优于web,web页面交互效果也稍差。原生应用对于用户来说是友好的,对于一个成熟的产品来说,也必须是原生应用(至少80%已上的页面是native写的)。这一点Facebook已经走过弯路了,曾经出了一款web应用,后来饱受批评而下架,改回原生开发。

那为什么我们还要使用混合开发呢?产品从有想法,到最后到用户手上,期间要经历很多过程,其中的一个过程是需求的验证和原型的开发,这个过程的迭代速度是极快的,不断的假设,再不断的实现和验证。我把这个过程命名为验证阶段。最后需求相对明确和趋于稳定下来,会进入到产品的实质开发阶段。

在验证阶段,如果使用原生的来做,开发的压力会比较大。Web技术发展多年,已经非常成熟,开发速度会比原生的快不少,对于需求的响应速度就能更快满足产品需要。对于iOS应用来说,还有一道障碍是苹果漫长的审核周期,这对于需要快速迭代的产品来说是很不爽的。这时候混合开发就派上用场了。对于需要验证和频繁更新的需求,使用web技术来做,可以规避发布新版本。在这个阶段,有些页面是原生的,有些是web的,保证产品始终处于一个比较完整的状态。这可以让产品尽早地交付产品经理、设计师、用研,以及测试用户,来验证需求。

在实质开发阶段,需要逐步地将混合页面过度到原生页面,尤其是对于交互和性能有所要求的页面。不然用户是不会接受的。

总结来说,混合开发有几个好处:

混合开发技术探究

混合开发技术主要需要解决两个问题:

打通Native & Web

iOS7以前,ObjC调用JS代码使用的是这个方法:stringByEvaluatingJavaScriptFromString 而JS要调用ObjC代码,一般的解决方案是先协议好一些事件,在WebView的delegate中去捕捉。

iOS7出了个框架:JavaScriptCore.Framework. 使用这个框架,让JavaScript和ObjC代码互相调用就方便而简单很多了。JavaScriptCore还做了ObjC和JS间的类型转换。 在拿到JavaScript的上下文(JSContext)之后,可以方便地注入变量和执行JS代码:

JSContext *context = [[JSContext alloc] init];
[context evaluateScript:@"console.log('hello world');"];

而要让JS调用ObjC代码,有两种方法:一种是通过block,另一种是实现JSExport协议。放在JSExport协议下的方法都可以暴露给JS。JavaScriptCore会自动生成一个Wrapper Object来桥接。可以参考HybridBridge的写法。

要在真正的项目中使用还需要对这个框架做一下封装。最基本的需要考虑以下几种场景:

优化WebView

一般来说WebView需要先请求资源,请求数据,然后再去渲染。这是一个耗时的过程,所以经常会看到WebView一直显示在loading。请求模板资源和数据跟网络情况有关,数据是可能经常变的,而资源的变化频率就比较小了。可以做个优化,把资源放到本地。这种优化可以减少页面大部分的响应时间。

资源也并不是一直不变的,如果这样的话,那就没办法利用混合开发的热更新。资源的增量打包和动态更新是另一项重要工作。当前端代码更新时,将增量部分打包,根据时间戳形成一个新的版本的zip包。客户端保存有当前使用的资源版本号,当App进入到后台时,根据保存的版本号向后端请求更新的资源。如果有新的资源则下载到本地,并解压覆盖旧的资源。

这种方法在优化加载时间的同时兼顾了热更新特性。

任何技术方案都有好有坏,用之有道才能扬长避短。