phonegap
phonegap 框架詳解
轉(zhuǎn)自:http://www.cnblogs.com/hubcarl/p/4216844.html首先, 來看一下phonegap 初始化流程以及Native 與 JS 交互流程圖。
?
說明:socket server模式下, phonegap.js 源碼實(shí)現(xiàn)的采用1 毫秒執(zhí)行一次XHR請求, ?當(dāng)Native ?JS 隊(duì)列里面有JS語句數(shù)據(jù)時(shí),才是真正的1毫秒調(diào)用一下; ?當(dāng)沒有數(shù)據(jù), scoket server 會(huì)阻塞10毫秒, 也就是XHR 要等10秒鐘才能收到結(jié)果,并進(jìn)行下一次的輪詢。
?
1、Activity繼承 DroidGap (extends PhonegapActivity)
從phonegap.xml 中加載白名單配置 和 log配置
2、loadUrl (每個(gè)Activity 都初始化一次)
》》初始化webview
》》初始化callbackServer
》》插件管理器PluginManager?
?
3、加載插件配置:
》》讀取 plugins.xml 配置,用map存儲(chǔ)起來。
| 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調(diào)用時(shí)通過別名來調(diào)用。
value:java具體實(shí)現(xiàn)類
web頁面調(diào)用(例如查找聯(lián)想人)
PhoneGap.exec(successCB, errorCB, "Contacts", "search", [fields, options]);
4、插件實(shí)現(xiàn)
》》編程java類,繼承Plugin類(Plugin 實(shí)現(xiàn)了IPlugin接口),并實(shí)現(xiàn)execute方法。
例如聯(lián)系人管理插件:
| 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 : 用來指定一個(gè)具體動(dòng)作? search 表示搜索聯(lián)系人 ?????* args: 方法參數(shù) ?????* callbackId:js與java指定一個(gè)標(biāo)識, ?????*/ ????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 初始化時(shí),如果loadUrl的url不是以file:// 開頭時(shí),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 ?關(guān)鍵代碼說明
?
phonegap.js在啟動(dòng)時(shí),首先會(huì)通過prompt("usePolling", "gap_callbackServer:")獲取調(diào)用方式: XHR 輪詢 OR prompt 輪詢, ?如果是XHR的話, 會(huì)啟動(dòng)XHR調(diào)用獲取http server端口 和token。
方法PhoneGap.Channel.join 啟動(dòng) js server 或者polling調(diào)用?
UsePolling 默認(rèn)為false。 通過var polling = prompt("usePolling", "gap_callbackServer:") 獲取調(diào)用方式。
| 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 首次啟動(dòng)獲取js調(diào)用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進(jìn)行通信,每一毫秒執(zhí)行一次JSCallback,從android socket獲取javascript執(zhí)行結(jié)果代碼,最后通過eval動(dòng)態(tài)執(zhí)行javascript
XHR調(diào)用, 通過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返回結(jié)果代碼片段 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、總結(jié)
1、phonegap android 插件管理器PluginManager初始化時(shí), 是每個(gè)Activity都要初始化一次, 數(shù)據(jù)都緩存一次, 導(dǎo)致同一份數(shù)據(jù)緩存多次。-- 暫不清楚為啥這樣實(shí)現(xiàn)? 難道是phonegap 框架是為單webview 實(shí)現(xiàn)的,如果有知道原因的請告知一下。
? ? ?2、同第1點(diǎn)一樣, Socket Server 每個(gè)Activity都會(huì)初始化一下, 如果loadUrl 的url類型不同,會(huì)不會(huì)導(dǎo)致scoket server狀體錯(cuò)亂,?待驗(yàn)證!
? ? ?3、phonegap 采用 prompt 和 XHR 輪詢機(jī)制,一是會(huì)導(dǎo)致手機(jī)耗電情況嚴(yán)重, 二是了解到prompt 調(diào)用是會(huì)阻塞js執(zhí)行的, 這樣導(dǎo)致影響到頁面加載速度。
?
? phonegap 已經(jīng)改名cordova, 在最新版本cordova 框架里面已經(jīng)去掉了socket server模式, 詳細(xì)請查看:http://www.cnblogs.com/hubcarl/p/4202784.html
轉(zhuǎn)載于:https://www.cnblogs.com/iverson-weng/p/5098582.html
總結(jié)
- 上一篇: 指针分析
- 下一篇: 看libevent所遇到的英语生词