JSBridge框架解決通信問題實現移動端跨平臺開發

      網友投稿 1028 2022-05-30

      一、跨平臺開發是趨勢

      目前主流的移動端平臺主要是Android和iOS,為了盡可能復用代碼和節省開發成本,各大巨頭都開發了自己的跨平臺框架,比如Facebook的React-Native、阿里的Weex、Cordova,以及今年Google開發者大會上介紹的Flutter框架。這些框架各有優缺點,但是到目前為止都沒有大規模地推廣開來,在我看來主要有以下幾個原因:

      1、開發者生態圈還不夠成熟

      RN是三大跨平臺框架中關注人最多、生態最活躍的框架,但是到目前為止也沒有到1.0版本(最新的release是0.57.8),更別說作為后來者的Weex和Flutter了。生態不成熟,意味著開發文檔少,可以使用的開源控件少,比如在RN上想做一個最基本的下拉刷新和上拉加載更多的listview都比較費勁。Weex已經貢獻給Apache,很久沒有更新release了。Flutter現在還在beta版本,其發展還有待觀察。

      2、性能問題

      雖然這幾大框架都對渲染性能做了優化,但是相比原生還是差一些,RN和weex都自己實現了一個瀏覽器內核(JSCore),因此多了一層js解析,渲染較慢。比如RN的listview,如果數據量太大就會出現卡頓。Flutter雖然自帶繪制引擎,但是跟原生比起來還是有一些距離。

      3、兼容問題

      雖然這三大平臺的初衷都是為了跨平臺(Write/Learn once, run everywhere),但在實際應用中還是需要耗費很多的精力去兼容和適配,比如RN在Android低端機器上表現就不盡如人意,連曾經RN的堅實擁護者Airbnb都宣布放棄使用RN了。

      4、開發集成成本

      三個框架都需要學習新的語言React/vue/dart,weex的最大優勢就是入門簡單,但是版本迭代慢,RN上手門檻高,開發調試難度大,集成RN和weex框架還會加入很多so文件,增加安裝包的大小(至少在10M左右),這還不包括第三方的library。Flutter因為剛出來,應用的人還不多,其效果還有待觀察。

      總結:雖然上述自主研發的跨平臺框架都或多或少地存在問題,但是移動開發的跨平臺是大勢所趨,可以節省開發成本,提高開發效率,迅速響應業務變化,現在主流的應用還是使用H5和原生的通信來實現跨平臺的開發。Android和iOS平臺都有自己內置的瀏覽器內核webkit框架,跨平臺的本質就是用H5/JS編寫的代碼能夠分別運行在Android和IOS的WebView中,從而實現一套代碼兩個平臺都能運行的目的。

      二、安卓跨平臺開發實踐

      在Android平臺上要實現Native和JS的通信主要通過WebViewClient和WebChromeClient兩個類來實現。

      WebViewClient的作用是幫助WebView處理各種通知、事件請求,其主要的方法有:onLoadResource、onPageStart、onPageFinished、onReceiveError、shouldOverrideUrlLoading等;

      WebChromeClient處理JS頁面的事件響應,比如網頁中的對話框、網頁圖標、網站標題、網頁的加載進度等事件,對應的響應方法有onJsAlert、onJsConfirm、onJsConsole、onProgressChanged、onReceiveIcon、onReceiveTitle等。

      要實現Java和JS通信就要:

      解決Java調JS;

      JSBridge框架解決通信問題實現移動端跨平臺開發

      JS調Java。

      Java調用JS通過loadUrl和evaluateJavaScript兩個方法。

      通過webview.loadUrl(“javascript:alert(‘hello world’)”),可以在android平臺將js代碼注入到html頁面,loadUrl方法可以直接調用js中定義的函數,也可以把android本地的assets目錄下的js文件以字符串的形式注入到html頁面中,但是這個注入時機一定要等到html頁面加載完畢才能做,即在WebViewClient.onPageFinished的回調函數中調用,這樣就相當于在html頁面中直接引用了js資源文件。對于客戶端來說,java調用js本質上是一個拼接js字符串的過程,但是調用loadUrl不能直接獲取js函數的返回值,而要實現Java調用js函數后。

      獲取js函數的返回值可以使用webview.evaluateJavaScript方法,但是該方法只有在android4.4及以上的版本才可以使用。其他用法和loadUrl一致。

      JS調用Java可以分為三種:對象映射、URL攔截、JS方法攔截。

      對象映射是通過webview.addJavascriptInterface(new JSObject(), “javaObject”),這樣可以js代碼中可以直接調用javaObject對象,從而實現JS調用Java的功能,但是這個方法在android4.2以下會有安全漏洞,利用反射機制調用Android API getRuntime執行shell命令進行攻擊,比如遍歷sdcard、發送短信、安裝木馬APK等。

      URL攔截是指在html頁面通過iframe.src、window.open、documention.location或者href,這四種方法都可以在html頁面中打開一個連接,從而會觸發Java中的WebViewClient.shouldOverrideUrlLoading方法。例如在js中執行

      在shouldOverrrideUrlLoading中可以根據約定的協議格式(Scheme)和協議名(Authority)獲取從JS中傳輸過來的數據(Data)。

      在JS中調用alert、console、prompt、confirm等方法就會觸發WebChromeClient的onJsAlert、onConsoleMessage、onJsPrompt、onJsConfirm方法的回調。比如在js中可以調用

      在onJsPrompt的message中可以獲取prompt的內容,然后根據約定的協議格式可以獲取數據。

      三、JSBridge框架

      為了解決JS和Native的通信問題,需要使用一個JSBridge框架(https://github.com/lzyzsd/JsBridge)用來負責H5和Java之間的通信,此時需要解決以下兩個問題:

      1)JS互相Java調用后如何回調,將responseData傳遞回去;

      2)JS調用Java有三種方法,如果選擇哪一種方法比較合適。

      針對問題1,可以在java端和js端定義一個數據結構: Message={callbackId:xxx, handleName:xxx,responseData:xxx,responseId:xxx}。將回調函數保存在callbackId中,當JS或者Java處理完數據回調的時候再將保存在callbackId的回調函數存放在responseId,相應的回調的數據存放在responseData中,這樣就能響應JS或者Java調用后的回調消息。

      Js調用Java的方法雖然有三種,但是addJavaScriptInterface存在安全性問題一般不建議使用,JS中的alert、console方法都會在Html頁面比較常用,confirm和prompt雖然不常用但是某些手機系統版本上會有對話框彈出,不通用,所以比較好的選擇是url攔截,可以通過iframe.src觸發shouldOverrideUrlLoading。

      JsBridge框架的使用主要分為:

      在H5頁面加載完畢注入一個本地的js文件;

      Java代碼中注冊BridgeHandler,用來處理JS發送過來的消息;

      在本地注入的js文件中定義_handleMessageFromNative,用來接收java傳遞過來的消息;

      因為客戶端注入js是異步的,所以需要在js文件中注冊Event-,成功后通知H5。

      Native調用JS,例如通過

      webview.loadUrl( "javascript:WebViewJavascriptBridge._handleMessageFromNative('{ \"callbackId\":\"JAVA_CB_2_559\",\"data\":\"just?data?from?java\" }')");

      這樣就可以調用JS的handleMessageFromNative方法,傳遞的數據格式是Message,callBackId響應js的回調,發送前會存儲到HashMap中,js回調的時候根據JAVA_CB_2_559找到對應的的回調函數處理js的響應數據,具體流程如下:

      Js調用Java,通過sendMessageQueue將傳遞的信息轉換成

      Message=?{data:?{…},?callbackId:?"cb_1_1234"}

      其中callbackId是js的回調函數。然后通過

      iframe.src=’yy://return/_fetchQueue/[{"data":"xxxx","callbackId":"cb_1_4321"}]’,

      觸發shouldOverrideUrlLoading方法,java處理完js傳遞過來的data后,將回調函數cb_1_4321設置到

      Message={responseId:?cb_1_4321,?responseData:XXX},

      這樣在js中就能處理回調函數。具體的流程圖如下:

      JsBridge框架提供兩種Handler方法,registerHandler方法需要傳入handler的名字,這樣需要iOS、Android、H5三方約定這個名字,因為H5開發的的業務需求變化比較快,而且H5調用原生的方法也是隨機的,所以每次都用registerHandler約定名字需要使用全局變量存放這些handler方法名不便于擴展,所以實際開發中使用defaultHanlder,H5調用原生方法的的時候約定一個cmd,即約定data={cmd:xxx,time:data:{…}},只要在原生代碼中對cmd命令有對應的功能,那么H5頁面就可以隨時調用原生的方法。

      JSBridge的改進建議,由于webview調用js方法的時候必須在主線程才能生效,所以偶然會出現java調用js失敗。另外,Js調用Java偶爾也會失敗,因為iframe機制不能保證每次都能觸發shouldOverrideUrlLoading回調。

      目前JSBridge采用的是url scheme的方式,如果不考慮Android4.2以下,iOS7以下,可以采用的交互,比如直接使用addJavaScriptInterface在JS頁面注入一個Native對象,將之前觸發u步驟變為使用這個Native對象向Native發送消息。這種方法只是一個可行的方案,實際使用過程中目前的JSBridge方案基本上滿足業務需求了。

      來源:宜信技術學院

      本文轉載自異步社區。

      原文鏈接:https://www.epubit.com/articleDetails?id=NN54c6e279-0a32-45aa-a900-1c4556a1d96a

      Java Android

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:記憶存儲、聲音還原、性格模仿……AI可以讓人類永生嗎?
      下一篇:深入理解Eureka之源碼解析
      相關文章
      久久精品国产亚洲av四虎| 亚洲精品无码av片| 在线观看亚洲AV日韩AV| 亚洲网站在线免费观看| 亚洲男人的天堂在线播放| 亚洲AV综合色一区二区三区| 九月丁香婷婷亚洲综合色| 亚洲午夜久久久久久久久电影网| 亚洲人成色77777在线观看大| 亚洲电影日韩精品 | 内射无码专区久久亚洲| 久久亚洲AV成人无码国产最大| 亚洲国产欧美国产综合一区| 亚洲第一成年网站视频| 亚洲AV无码资源在线观看| 亚洲AV无码专区国产乱码不卡| 亚洲av永久中文无码精品综合| 国产成人综合亚洲一区| 国产亚洲精品美女2020久久| 亚洲国产精品人人做人人爽 | 国产亚洲综合精品一区二区三区| 国产精品亚洲专区无码WEB| 综合偷自拍亚洲乱中文字幕| 亚洲av中文无码| av在线亚洲欧洲日产一区二区| 久久久亚洲精品蜜桃臀| 亚洲人成伊人成综合网久久久| 国产亚洲精品观看91在线| 亚洲va久久久噜噜噜久久男同| 亚洲国产精品lv| 亚洲理论片在线观看| 亚洲天堂男人影院| 亚洲av无码专区在线电影| 亚洲欧洲久久av| 国产亚洲欧洲Aⅴ综合一区| 精品国产亚洲一区二区三区 | 亚洲一区中文字幕久久| 亚洲国产综合精品| 亚洲精品无码人妻无码| 亚洲av午夜成人片精品电影 | 久久乐国产综合亚洲精品|