Android中Hybrid實(shí)戰(zhàn)

目錄

1肖揣、Hybrid整體結(jié)構(gòu)
2拭嫁、橋接層
3可免、基礎(chǔ)通信層
4、打開離線插件的流程
5做粤、離線插件數(shù)據(jù)預(yù)加載優(yōu)化

1浇借、Hybrid層次結(jié)構(gòu)

Hybrid結(jié)構(gòu)層次

(1)H5頁面層。
(2)橋接層:BridgeJs是一個(gè).js文件怕品,是NA和H5通信的橋梁妇垢,WebView在加載url之前需要將BridgeJs前置注入。
(3)基礎(chǔ)通信層:該層主要由BridgeWebView堵泽、BridgeManager修己、WebPlugin組成,BridgeWebView提供了基本的頁面加載迎罗,并捕獲BridgeJs發(fā)送過來的事件交給BridgeManager進(jìn)行處理睬愤;BridgeManager具備BridgeWebView的控制能力,負(fù)責(zé)處理NA向H5以及H5向NA的消息處理纹安;WebPlugin是離線化插件尤辱,為了加速H5頁面的展示,可將某個(gè)業(yè)務(wù)的h5厢岂、css光督、js、圖片等資源打包塔粒,并離線化至本地结借,在打開相應(yīng)頁面的時(shí)候只需獲取其對應(yīng)頁面的數(shù)據(jù),省去h5卒茬、css船老、js咖熟、圖片等資源的下載時(shí)間。
(4)協(xié)議分發(fā)層:該層是一個(gè)總體的demo協(xié)議分發(fā)器柳畔,將收到的協(xié)議分發(fā)到各個(gè)協(xié)議實(shí)現(xiàn)層進(jìn)行處理馍管。
(5)協(xié)議實(shí)現(xiàn)層:該層針對demo協(xié)議不同的scheme,分別對應(yīng)不同的實(shí)現(xiàn)薪韩。NativePageCall用于APP內(nèi)各個(gè)頁面的跳轉(zhuǎn)确沸;WebSDKCall是用于為H5提供各種NA能力,WebPluginCall用于打開本地離線化插件俘陷。
(6)Native層:該層為客戶端App層罗捎,為上述幾種協(xié)議提供能力調(diào)用和支持。

2岭洲、橋接層

2.1宛逗、BridgeJs是什么坎匿?

BridgeJs是一個(gè).js文件盾剩,是NA和H5通信的橋梁,(作用是做隔離)替蔬。具體來說就是H5調(diào)用NA能力或者打開NA頁面必須通過調(diào)用BridgeJs中的方法來通知NA告私,NA也必須調(diào)用BridgeJs中的方法來給H5頁面發(fā)送消息。

2.2承桥、BridgeJs的注入方式

WebView注入BridgeJs文件的方式為驻粟,先將該文件讀入內(nèi)存作為BridgeJs,Android4.4以前通過loadUrl("javascript:" + BridgeJs)進(jìn)行注入凶异,BridgeJS注入完畢后蜀撑,在JS函數(shù)尾部通過onConsoleMessage向NA發(fā)起通知,標(biāo)記注入完畢的事件剩彬;4.4后的版本酷麦,可使用evaluateJavascript (String script, ValueCallback<String> resultCallback)方法注入并實(shí)現(xiàn)回調(diào),注入完成后可向?qū)?yīng)H5頁面種入NA基本信息喉恋,供H5使用并調(diào)用H5中Ready方法觸發(fā)H5頁面渲染沃饶。

3、 基礎(chǔ)通信層

3.1轻黑、BridgeWebView

由WebView+TitleBar+ProgressBar構(gòu)成糊肤,ProgressBar根據(jù)onProgressChanged(WebView view, int newProgress)顯示當(dāng)前頁面加載進(jìn)度,避免頁面加載時(shí)無狀態(tài)氓鄙,TitleBar支持多種主題馆揉,為H5提供三種UI操作元素(返回按鈕,標(biāo)題抖拦,功能按鈕)升酣;WebView是作為H5頁面的容器勤讽,在加載頁面的同時(shí),也負(fù)責(zé)捕獲頁面消息和注入JS拗踢。

3.2脚牍、BridgeManager

通過重寫shouldOverrideUrlLoading(WebView view, String url),將收到的重定向url交給BridgeManager去攔截巢墅,BridgeManager通過調(diào)用SchemeDispatcher. onDispatch(String url)的去處理消息诸狭;如果BridgeWebView主動向H5發(fā)送消息,則通過BridgeManager執(zhí)行相應(yīng)的javascript方法君纫。

3.3驯遇、 WebPlugin

3.3.1、 WebPlugin的作用

WebPlugin是為了加速H5頁面的展示速度蓄髓,我們打開一個(gè)h5頁面的流程大致如下


h5頁面加載流程

離線化插件的大致思路是將H5頁面中的html叉庐、js、css以及一些靜態(tài)的圖片資源打包離線化至本地会喝,在打開相應(yīng)頁面的時(shí)候從本地去打開陡叠,然后只需獲取對應(yīng)頁面的數(shù)據(jù),省去html肢执、js枉阵、圖片等資源的下載時(shí)間。

3.3.2预茄、 WebPlugin構(gòu)成

一個(gè)H5離線化插件一般對應(yīng)某個(gè)業(yè)務(wù)兴溜。

離線化插件一般對應(yīng)某個(gè)業(yè)務(wù),這個(gè)業(yè)務(wù)通常包括多個(gè)H5頁面耻陕。
離線化插件的內(nèi)容主要包括兩個(gè)方面:

1拙徽、多個(gè)H5頁面中的html、js诗宣、css以及一些靜態(tài)的圖片資源
2膘怕、config.json文件。
config.json文件是插件配置文件梧田,描述了這個(gè)插件中頁面的名稱和路徑的映射關(guān)系淳蔼,例如:

config文件

3.3.3、離線插件的工作流程

離線插件整體思路.png

(1)裁眯、運(yùn)營平臺上傳打包好的離線插件鹉梨;
(2)、server端發(fā)下離線插件配置穿稳;
(3)存皂、App端根據(jù)server下發(fā)配置下載和更新離線插件。

(3.1)、server端下發(fā)離線插件配置包括一個(gè)allMd5值和一個(gè)plugin_list插件列表旦袋,外層的md5表示所有插件zip包共同計(jì)算的總md5值骤菠,用于和本地總md5對比,判斷是否有插件要更新疤孕。plugin_list中每個(gè)插件包含plugin_id商乎,url和md5,plugin_id唯一標(biāo)識該插件祭阀,并作為data/data/package name/Plugins/目錄下插件的路徑名鹉戚,url為插件下載地址,md5為插件zip包的md5值专控,用于判斷當(dāng)前插件是否需要更新及下載完成后校驗(yàn)該包的完整性抹凳。

離線插件分為正常更新和緊急更新:

3.3.4離線插件的正常更新

離線插件正常更新.png

(1)首先檢測當(dāng)前是否有更新任務(wù)隊(duì)列正在運(yùn)行,如果有伦腐,則直接返回赢底;
(2)檢測接口返回的allMD5值與本地sharedPreferences記錄的上次成功更新的總md5值是否相同,如果相同柏蘑,則直接返回幸冻,否則繼續(xù);

(3)為每個(gè)plugin配置更新任務(wù)PluginUpdateTask辩越,然后放到線程池中執(zhí)行嘁扼,且所有的Task及其狀態(tài)被記錄在一個(gè)HashMap<String, PluginUpdateState>中,用于判斷是否所有的插件都更新完成并且成功黔攒;

(4)PluginUpdateTask實(shí)現(xiàn)單個(gè)插件的更新流程:先檢查本地相同pluginId的md5是否與新的相同,若相同强缘,則直接返回True督惰,否則,依次執(zhí)行插件下載旅掂、md5完整性校驗(yàn)赏胚、刪除舊插件、解壓商虐,最后將該插件新的md5值記錄到本地觉阅。(每個(gè)插件下載成功或者失敗都將其狀態(tài)記錄到HashMap<String, PluginUpdateState>中);

(5)檢測是否所有的插件更新完成并且成功秘车,如果是典勇,則將allMd5值記錄到本地,否則等待下次更新或者緊急更新叮趴。

3.3.5割笙、離線包緊急更新

Plugin緊急更新用于一些極端case,在某些場景下眯亦,用戶點(diǎn)擊進(jìn)入離線插件伤溉,可能會遭遇打開失敯懵搿(例如插件被清理,上一次更新異常等)乱顾,這種情況下板祝,需要根據(jù)插件的pluginId,為該plugin開啟獨(dú)立的插件下載任務(wù)走净,且不與正常的更新檢測任務(wù)耦合扔字。流程如下:

離線插件緊急更新

(1)插件啟動失敗,進(jìn)入BridgeWebView頁温技,顯示loading革为;

(2)根據(jù)pluginId,查找內(nèi)存中的PluginBean舵鳞,若找到震檩,則直接開始下載,若未找到蜓堕,則重新拉取離線插件接口抛虏,獲取PluginBean,

(3)為PluginBean配置PluginEmergencyTask套才,放到線程池中開啟緊急下載任務(wù)迂猴,復(fù)用單個(gè)插件下載邏輯下載該插件。(不同的是此時(shí)不需要對該plugin新的md5值和本地md5只校驗(yàn)背伴,因?yàn)槿绻窃摬寮G闆r下下載成功沸毁,但是被刪除,校驗(yàn)md5值會直接返回傻寂,無法下載該插件)息尺;

(4)若下載成功則重新打開該拆件,否則疾掰,關(guān)閉頁面搂誉,并提示失敗。

4静檬、打開離線插件的流程:

打開離線插件的流程

一個(gè)打開plugin的demo協(xié)議是這樣的:
demo://plugin?pluginId=xxx&pageName=xxx

(1)根據(jù)pluginId炭懊,獲取該插件的目錄pluginDir,一般為/data/data/package name/pluginId
(2)進(jìn)入插件目錄拂檩,找到config.json文件侮腹,并將其讀取為WebPluginConfigModel;
(3)根據(jù)的pageName广恢,可以查找到對應(yīng)頁面的pagePath凯旋;
(4)通過BridgeWebView打開本地頁面"file://" + pluginDir + pageFilePath + "?" + query。

5、離線插件數(shù)據(jù)預(yù)加載優(yōu)化

為了進(jìn)一步加快離線包的頁面顯示速度至非,提出了離線包預(yù)加載數(shù)據(jù)钠署,webview打開一個(gè)url之前,發(fā)起一個(gè)本地網(wǎng)絡(luò)請求去請求即將打開的h5頁面的數(shù)據(jù)荒椭。

1谐鼎、預(yù)加載H5頁面的前提:

在離線包的config.json文件中為需要預(yù)加載的頁面添加預(yù)加載數(shù)據(jù)PreloadRequest,主要包含預(yù)加載的url趣惠,請求方法狸棍,請求參數(shù)等。

2味悄、H5離線插件頁面預(yù)加載數(shù)據(jù)流程如下:

H5離線插件數(shù)據(jù)預(yù)加載

打開預(yù)加載h5頁面的url一般是
demo://plugin?pluginId=xxx&pageName=xxx&requestPreload=true

(1)首先根據(jù)pluginId從對應(yīng)插件的config配置文件中讀取相應(yīng)頁面的預(yù)加載數(shù)據(jù)PreloadRequest草戈。

(2)根據(jù)預(yù)加載數(shù)據(jù)PreloadRequest中的url,請求方法侍瑟,請求參數(shù)等利用本地okhttp框架構(gòu)建一個(gè)網(wǎng)絡(luò)請求唐片,去獲取數(shù)據(jù)。

(3)當(dāng)數(shù)據(jù)獲取成功涨颜,如果jsbridge注入完成费韭,則調(diào)用其回調(diào)方法PreloadFinish,將獲取到的數(shù)據(jù)傳遞給h5頁面庭瑰;如果jsbridge未注入完成星持,則將獲取的數(shù)據(jù)緩存到內(nèi)存,待jsbridge注入完成弹灭,在其注入完成的回調(diào)中督暂,調(diào)用h5頁面的回調(diào)方法PreloadFinish將數(shù)據(jù)傳遞給h5頁面。h5頁面收到數(shù)據(jù)后鲤屡,并可根據(jù)數(shù)據(jù)去填充頁面损痰。

注:我們用一個(gè)boolean的變量標(biāo)記jsbridge是否注入完成,jsbridge注入完成酒来,會有一個(gè)回調(diào),我們可以在回調(diào)中將這個(gè)變量置位true肪凛,標(biāo)記注入完成堰汉。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市伟墙,隨后出現(xiàn)的幾起案子翘鸭,更是在濱河造成了極大的恐慌,老刑警劉巖戳葵,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件就乓,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)生蚁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進(jìn)店門噩翠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人邦投,你說我怎么就攤上這事伤锚。” “怎么了志衣?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵屯援,是天一觀的道長。 經(jīng)常有香客問我念脯,道長狞洋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任绿店,我火速辦了婚禮吉懊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘惯吕。我一直安慰自己惕它,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布废登。 她就那樣靜靜地躺著淹魄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪堡距。 梳的紋絲不亂的頭發(fā)上甲锡,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天,我揣著相機(jī)與錄音羽戒,去河邊找鬼缤沦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛易稠,可吹牛的內(nèi)容都是我干的缸废。 我是一名探鬼主播,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼驶社,長吁一口氣:“原來是場噩夢啊……” “哼企量!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起亡电,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤届巩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后份乒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恕汇,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腕唧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瘾英。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枣接。...
    茶點(diǎn)故事閱讀 40,926評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖方咆,靈堂內(nèi)的尸體忽然破棺而出月腋,到底是詐尸還是另有隱情,我是刑警寧澤瓣赂,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布榆骚,位于F島的核電站,受9級特大地震影響煌集,放射性物質(zhì)發(fā)生泄漏妓肢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一苫纤、第九天 我趴在偏房一處隱蔽的房頂上張望碉钠。 院中可真熱鬧,春花似錦卷拘、人聲如沸喊废。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽污筷。三九已至,卻和暖如春乍赫,著一層夾襖步出監(jiān)牢的瞬間瓣蛀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工雷厂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惋增,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓改鲫,卻偏偏與公主長得像诈皿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子像棘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評論 2 361

推薦閱讀更多精彩內(nèi)容