跨平台PhoneGap技术架构五:PhoneGap类间调用关系及Js和Java交互原理

前面几篇文章主要讲解了PhoneGap几个重要的类,如果看到这里,相信大家对PhoneGap也有了一定的了解。

PhoneGap类间调用关系

在讲解PhoneGap的交互原理之前,我们把原来的内容串讲一下,以加深理解。请看下面的类间调用关系图:

在我们创建Android应用程序的时候,一般会先创建一个Activity。PhoneGap应用程序创建时Activity应继承DroidGap类。当Activity启动时,系统会调用onCreate方法。在DroidGap类中,复写了Activity的onCreate方法。

在DroidGap的onCreate方法中,对Window做了一些设置,并设置了WebView的布局。最后设置了音量硬件控制功能。代码如下:

onCreate
 1    /**
 2      * Called when the activity is first created.
 3      *
 4      * @param savedInstanceState
 5      */
 6     @SuppressWarnings("deprecation")
 7     @Override
 8     public void onCreate(Bundle savedInstanceState) {
 9         //preferences = new PreferenceSet();
10 
11         LOG.d(TAG, "DroidGap.onCreate()");
12         super.onCreate(savedInstanceState);
13 
14         if(!this.getBooleanProperty("showTitle", false))
15         {
16             getWindow().requestFeature(Window.FEATURE_NO_TITLE);
17         }
18 
19         if(this.getBooleanProperty("setFullscreen", false))
20         {
21             getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
22                     WindowManager.LayoutParams.FLAG_FULLSCREEN);
23         }
24         else
25         {
26             getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
27                     WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
28         }
29         // This builds the view.  We could probably get away with NOT having a LinearLayout, but I like having a bucket!
30         Display display = getWindowManager().getDefaultDisplay();
31         int width = display.getWidth();
32         int height = display.getHeight();
33 
34         root = new LinearLayoutSoftKeyboardDetect(this, width, height);
35         root.setOrientation(LinearLayout.VERTICAL);
36         root.setBackgroundColor(this.backgroundColor);
37         root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
38                 ViewGroup.LayoutParams.MATCH_PARENT, 0.0F));
39 
40         // Setup the hardware volume controls to handle volume control
41         setVolumeControlStream(AudioManager.STREAM_MUSIC);
42     }

 

然后PhoneGap应用程序调用了loadUrl方法,

super.loadUrl("file:///android_asset/www/index.html");

 

之前说过,loadUrl可以看作是整个应用程序的入口函数。

loadUrl函数会调用Init方法,创建一个CordovaWebView,并设置了CordovaWebViewClient和CordovaChromeClient。

在实例化CordovaWebView时,对PluginManager做了初始化工作,而在CordovaWebViewClient的onPageStarted方法里初始化并启动CallbackServer。

CordovaWebViewClient的onJsPrompt方法截获Web端的JavaScript消息,调用PluginManager的exce方法执行插件。

插件执行成功后调用CallbackServer的sendJavaScript方法给Js端返回回调Js代码。

这就是PhoneGap类间的调用关系,整个PhoneGap工作流程大概也就清晰了。

Js和Java交互原理
  • js↔java同步过程

同步处理:

从js的prompt到WebChromeClient的onJSPrompt是一个跨线程的同步调用过程,如上图:

在cordova.js文件中,可以找到如下代码:

var r = prompt(JSON.stringify(args), "gap:"+JSON.stringify([service, action, callbackId, true]));

这句prompt便实现了本地代码调用。本地代码通过WebChromeClient拦截onJsPrompt回调,利用gap:开头标志得知是调用本地插件请求,然后向PluginManager转发该请求。PluginManager将会根据参数来查找并执行具体插件方法。

js层通过prompt向本地发送poll请求,本地将从CallBackServer中拿出下一个回调返回给js层。

  • js↔java异步过程

异步处理:

为了区别异步和同步。若prompt返回的是空字符串,那么将认为是异步调用。此时PhoneGap会在JS层保留回调函数,待本地层向CallBackServer发送回调后进行执行。
本地层怎么区别哪个回调?PhoneGap对此的处理十分简单,在cordova.js中定义了一个callbackId的自增种子,并将每个callBack插入callBacks中去。无论同步异步,每个plugin调用都将得到一个流水号码作为回调标识。这个回调标识在prompt阶段便传递到了本地层。当本地层的Plugin异步结束后,便可以根据该callbackId找到回调。并向CallBackServer发送回调通知。

posted @ 2012-07-16 23:12  嗷桑  阅读(3388)  评论(3编辑  收藏  举报