。PhoneGap是开源的,大家可以去官网下载源码自己来研究,下面只是简单分析一下它的实现原理。
首先大家会想到的问题就是,既然是做成native app,那么肯定会用到系统相关的api的呀?比如联系人呀、摄像头、陀螺仪等等……Html是怎么调用到这些系统api的呢?实际上,PhoneGap主要完成的功能就是这个:将这些几乎每个手机系统共有的功能特性按照各个系统平台系统的api,用js封装起来,通过js提供统一的调用接口,所以PhoneGap开发基本上无需关心系统实现,只用跟js代码打交道就好了。当然,这样通过js提供的接口很有限,当我们需要其他PhoneGap没有提供的系统功能时就只能自己动手了。
所以我们也要像PhoneGap一样,能够让native code和js code相互调用和通信,能够显现这个的话,那么我们就能对PhoneGap任意拓展了,甚至自己完成一个类PhoneGap框架。
以Android为例,下面介绍实现过程。
如何实现JS和Native Code 相互调用:
1 首先我们需要在Activity中加入一个WebView控件。
2 注册JS调用接口:
WebView.addJavascriptInterface(new runJavaScript(), "myjs");
runJavaScript是js回调的native code接口,具体代码如下:
final class runJavaScript{ public void runOnAndroidJavaScript(final String str){ h.post(new Runnable(){ public void run() { wv.loadUrl("javascript:get4Android("+ contactInfo + ")"); } }); } }
3 从本地调用JS函数:CallByNative()是js中实现的一个方法,可以通过下面的接口直接调用js文件中的function实现。
WebView.loadUrl("javascript:CallByNative()");
4 JS调用Native API:
window.myjs.runOnAndroidJavaScript();
协议 or 参数传递
使用json在js和native code之间传递参数是一个比较好的方法。以笔者实现的一个拉取本地联系人的Demo为例,数据的传递过程如下:
json是一种比较灵活而高效的格式,能够满足基本的数据通信的要求。
到此我们解决js和native code相互调用的问题,并且通过json能够进行数据的传输,实际上PhoneGap主要也就是实现了这些功能(当然,对各平台通用接口进行封装提供统一的js调用接口也是PhoneGap很重要的功能)。但是,仅仅这样的解决方案是无法满足产品开发的要求的,PhoneGap的某些致命缺陷需要我们自己动手来解决、并进行优化。
PhoneGap 存在的问题:
1 图形性能:渲染效率低
2 响应延迟:点击/输入
3 加载延迟:重内核/后退缓存
4 通信薄弱:只能轮询
对于1和4,这是html固有的缺陷,很难通过一般手段来改进,而3可以通过对页面进行精心的设计来避免这个问题。主要的设计方法包括用隐藏文本域来避免页面跳转等方法,这里不再详述。我们将主要精力放在对第2点,也就是UI响应的优化上。
在Android上直接运行PhoneGap的demo会发现,每一次点击的响应延迟基本在1s以上,这个严重影响了用户体验的流畅性,是完全不能接受的。好在这样的延迟响应不是性能问题,而是webkit内核对事件的处理逻辑导致的。
由于webkit最初是为pc设计的浏览器内核,因此webview在对事件进行处理时,要考虑的很全面。包括单击、双击、移动、按下、释放等事件,实际上最底层的事件就只有按下、释放和move这几个,其他如单击、双击等都是通过对它们的组合进行判断的,判断的逻辑如下:
通过上图大家应该能明白,在判断是单机还是双击时,系统需要一个延迟时间的,即300ms内连续收到两次点击事件,那么系统就认为发生了一次双击时间,否则就是两次单机而已。正是由于300ms这个时间窗口导致系统对点击反馈的延迟。然后,在手机上,我们是不需要处理双击这个事件的,所以我们可以改写webview这部分的处理逻辑,跳过对双击事件判断的等待,消除”300ms”的延时处理,就能让我们的UI快速单击单机事件了。
至此,优化后的PhoneGap才能更好的满足我们的产品需求。上面的优化只是针对Android平台,实际上在iOS上则无需这样进行优化PhoneGap就能获得很好的表现,因为Safari内核已经对这种情况有过优化了。