phonegap

phonegap 框架详解

 转自:http://www.cnblogs.com/hubcarl/p/4216844.html

首先, 来看一下phonegap 初始化流程以及Native 与 JS 交互流程图。

 

说明:socket server模式下, phonegap.js 源码实现的采用1 毫秒执行一次XHR请求,  当Native  JS 队列里面有JS语句数据时,才是真正的1毫秒调用一下;  当没有数据, scoket server 会阻塞10毫秒, 也就是XHR 要等10秒钟才能收到结果,并进行下一次的轮询。

 

1、Activity继承 DroidGap (extends PhonegapActivity)

从phonegap.xml 中加载白名单配置 和 log配置


2、loadUrl (每个Activity 都初始化一次)

》》初始化webview
》》初始化callbackServer
》》插件管理器PluginManager 

 

3、加载插件配置:

》》读取 plugins.xml 配置,用map存储起来。

1
2
3
4
5
6
7
< plugins >
< plugin  name="Camera" value="com.phonegap.CameraLauncher"/>
< plugin  name="Contacts" value="com.phonegap.ContactManager"/>
< plugin  name="Crypto" value="com.phonegap.CryptoHandler"/>
< plugin  name="File" value="com.phonegap.FileUtils"/>
< plugin  name="Network Status" value="com.phonegap.NetworkManager"/>
</ plugins >

说明:
name 是别名,javascript调用时通过别名来调用。
value:java具体实现类

web页面调用(例如查找联想人)
PhoneGap.exec(successCB, errorCB, "Contacts", "search", [fields, options]);


4、插件实现

》》编程java类,继承Plugin类(Plugin 实现了IPlugin接口),并实现execute方法。
例如联系人管理插件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public  class  ContactManager  extends  Plugin{
     /**
      * action : 用来指定一个具体动作  search 表示搜索联系人
      * args: 方法参数
      * callbackId:js与java指定一个标识,
      */
     public  PluginResult execute(String action, JSONArray args, String callbackId) {
         try  {
             if  (action.equals( "search" )) {
                 JSONArray res = contactAccessor.search(args.getJSONArray( 0 ), args.optJSONObject( 1 ));
                 return  new  PluginResult(status, res,  "navigator.contacts.cast" );
             }
             else  if  (action.equals( "save" )) {
                 String id = contactAccessor.save(args.getJSONObject( 0 ));
                 if  (id !=  null ) {
                                   JSONObject res = contactAccessor.getContactById(id);
                                       if  (res !=  null ) {
                                          return  new  PluginResult(status, res);
                                      }
                 }
             }
             else  if  (action.equals( "remove" )) {
                 if  (contactAccessor.remove(args.getString( 0 ))) {
                     return  new  PluginResult(status, result);                   
                 }
             }
             // If we get to this point an error has occurred
                 JSONObject r =  new  JSONObject();
                     r.put( "code" , UNKNOWN_ERROR);
                             return  new  PluginResult(PluginResult.Status.ERROR, r);
         catch  (JSONException e) {
             Log.e(LOG_TAG, e.getMessage(), e);
             return  new  PluginResult(PluginResult.Status.JSON_EXCEPTION);
         }
     }
}

  


5、polling和server初始化


android DroidGap 初始化时,如果loadUrl的url不是以file:// 开头时,polling = true, 否则是socket server方式

代码见CallbackServer.java 类init方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public  void  init(String url) {
     //System.out.println("CallbackServer.start("+url+")");
     // Determine if XHR or polling is to be used
     if  ((url !=  null ) && !url.startsWith( "file://" )) {
        this .usePolling =  true ;
        this .stopServer();
     }
     else  if  (android.net.Proxy.getDefaultHost() !=  null ) {
         this .usePolling =  true ;
         this .stopServer();
     }
     else  {
         this .usePolling =  false ;
         this .startServer();
     }
}

  


6、phonegap.js  关键代码说明

 

phonegap.js在启动时,首先会通过prompt("usePolling", "gap_callbackServer:")获取调用方式: XHR 轮询 OR prompt 轮询,  如果是XHR的话, 会启动XHR调用获取http server端口 和token。


方法PhoneGap.Channel.join 启动 js server 或者polling调用 

UsePolling 默认为false。 通过var polling = prompt("usePolling", "gap_callbackServer:") 获取调用方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
PhoneGap.Channel.join( function  () {
 
     // Start listening for XHR callbacks
     setTimeout( function  () {
       if  (PhoneGap.UsePolling) {
         PhoneGap.JSCallbackPolling();
       }
       else  {
         console.log( 'PhoneGap.Channel.join>>>>>>>>>>>>>>>>>>>>>>>>>' );<br>       <span style= "color: #ff6600;" //phonegap js 首次启动获取js调用Native方式</span>
         var  polling = prompt( "usePolling" "gap_callbackServer:" );
         PhoneGap.UsePolling = polling;
         if  (polling ==  "true" ) {
           PhoneGap.UsePolling =  true ;
           <span style= "color: #ff6600;" >PhoneGap.JSCallbackPolling();</span>
         }
         else  {
           PhoneGap.UsePolling =  false ;
          <span style= "color: #ff6600;" > PhoneGap.JSCallback();</span>
         }
       }
     }, 1);
}

  

XHR轮询:PhoneGap.JSCallback方法

通过XHR 与java端 socket进行通信,每一毫秒执行一次JSCallback,从android socket获取javascript执行结果代码,最后通过eval动态执行javascript

XHR调用, 通过prompt 获取socket端口 和 token(uuid)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
if  (PhoneGap.JSCallbackPort ===  null ) {
    PhoneGap.JSCallbackPort = <span style= "color: #ff6600;" >prompt( "getPort" "gap_callbackServer:" );</span>
    console.log( 'PhoneGap.JSCallback getPort>>>>>>>>>>>>>>>>>>>>>>>>>:'  + PhoneGap.JSCallbackPort);
}
if  (PhoneGap.JSCallbackToken ===  null ) {
  PhoneGap.JSCallbackToken =<span style= "color: #ff6600;" > prompt( "getToken" "gap_callbackServer:" );</span>
  console.log( 'PhoneGap.JSCallback getToken>>>>>>>>>>>>>>>>>>>>>>>>>:'  + PhoneGap.JSCallbackToken);
}
xmlhttp.open( "GET" "http://127.0.0.1:"  + PhoneGap.JSCallbackPort +  "/"  + PhoneGap.JSCallbackToken,  true );
xmlhttp.send();
 
XHR返回结果代码片段
var  msg = decodeURIComponent(xmlhttp.responseText);
setTimeout( function  () {
try  {
     var  t = eval(msg);
}
catch  (e) {
   // If we're getting an error here, seeing the message will help in debugging
   console.log( "JSCallback: Message from Server: "  + msg);
   console.log( "JSCallback Error: "  + e);
}
  }, 1);
  <span style= "color: #ff6600;" >setTimeout(PhoneGap.JSCallback, 1);</span><br>}

  

prompt轮询: PhoneGap.JSCallbackPolling方法

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<span style= "color: #ff6600;" >PhoneGap.JSCallbackPolling</span> =  function  () {
 
     // Exit if shutting down app
     if  (PhoneGap.shuttingDown) {
       return ;
     }
 
     // If polling flag was changed, stop using polling from now on
     if  (!PhoneGap.UsePolling) {
       PhoneGap.JSCallback();
       return ;
     }
 
     var  msg = prompt( "" "gap_poll:" );
     if  (msg) {
       setTimeout( function  () {
         try  {
           var  t = eval( ""  + msg);
         }
         catch  (e) {
           console.log( "JSCallbackPolling: Message from Server: "  + msg);
           console.log( "JSCallbackPolling Error: "  + e);
         }
       }, 1);
       <span style= "color: #ff6600;" >setTimeout(PhoneGap.JSCallbackPolling, 1);</span>
     }
     else  {
       setTimeout(PhoneGap.JSCallbackPolling, PhoneGap.JSCallbackPollingPeriod);
     }
   };

  

 7、总结

  1、phonegap android 插件管理器PluginManager初始化时, 是每个Activity都要初始化一次, 数据都缓存一次, 导致同一份数据缓存多次。-- 暂不清楚为啥这样实现? 难道是phonegap 框架是为单webview 实现的,如果有知道原因的请告知一下。

     2、同第1点一样, Socket Server 每个Activity都会初始化一下, 如果loadUrl 的url类型不同,会不会导致scoket server状体错乱, 待验证!

     3、phonegap 采用 prompt 和 XHR 轮询机制,一是会导致手机耗电情况严重, 二是了解到prompt 调用是会阻塞js执行的, 这样导致影响到页面加载速度。

 

  phonegap 已经改名cordova, 在最新版本cordova 框架里面已经去掉了socket server模式, 详细请查看:http://www.cnblogs.com/hubcarl/p/4202784.html

转载于:https://www.cnblogs.com/iverson-weng/p/5098582.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值