天天看點

聊一聊橋接(JSBridge)的原理

如今的網際網路時代也稱移動網際網路時代,基本上每個人每天都會花費大量時間在移動裝置上,早期的移動端應用大都使用原生開發(android,ios),而現在的移動開發技術選型上基本都是混合開發(Hybrid),混合開發是一種開發模式,指使用多種開發模型開發App,通常會涉及到兩大類技術:原生Native、Web H5

原生技術主要指iOS(Objective C)、Android(Java),原生開發效率較低,開發完成需要重新打包整個App,釋出依賴使用者的更新,性能較高功能覆寫率更高,釋出流程較為複雜

Web H5主要由HTML、CSS、JavaScript組成,Web可以更好的實作釋出更新,跨平台也更加優秀,但性能較低,功能實作也受限

混合開發的意義就在于吸取兩者的優點,而且随着手機硬體的更新疊代、系統(Android 5.0+、ISO 9.0+)對于Web特性的較好支援,H5的劣勢被逐漸縮小

原生、Web互相通信都離不開<code>JSBridge</code>。

在<code>Hybrid</code>模式下,H5會經常需要使用<code>Native</code>的功能,比如打開二維碼掃描、調用原生頁面、擷取使用者資訊等,同時Native也需要向Web端發送推送、更新狀态等,而<code>JavaScript</code>是運作在單獨的<code>JS Context</code>中<code>(Webview容器、JSCore等)</code>,與原生有運作環境的隔離,是以需要有一種機制實作Native端和Web端的雙向通信,這就是<code>JSBridge</code>:以JavaScript引擎或Webview容器作為媒介,通過協定協定進行通信,實作Native端和Web端雙向通信的一種機制。

通過JSBridge,Web端可以調用Native端的Java接口,同樣Native端也可以通過JSBridge調用Web端的JavaScript接口,實作彼此的互相調用。

首先了解下<code>webView</code>,<code>webView</code>是移動端(原生)提供的運作JavaScript的環境,它是一種嵌入式浏覽器,原生應用可以用它來展示網絡内容。可與頁面JavaScript互動,實作混合開發,其中<code>Android</code>和<code>iOS</code>又有些不同:

<code>Android</code>的<code>WebView</code>采用的是低版本和高版本使用了不同的webkit核心,4.4後直接使用了Chrome。

<code>iOS</code>中<code>UIWebView</code>算是自<code>IOS2</code>就有,但性能較差,特性支援較差,<code>WKWebView</code>是<code>iOS8</code>之後的更新版,性能更強特性支援也較好。

<code>WebView</code>控件除了能加載指定的url外,還可以對URL請求、JavaScript的對話框、加載進度、頁面互動進行強大的處理,之後會提到攔截請求、執行JS腳本都依賴于此。

Web端和Native可以類比于Client/Server模式,Web端調用原生接口時就如同Client向Server端發送一個請求類似,JSBridge在此充當類似于HTTP協定的角色,實作JSBridge主要是兩點:

将Native端原生接口封裝成JavaScript接口

将Web端JavaScript接口封裝成原生接口

聊一聊橋接(JSBridge)的原理

首先來說Native端調用Web端,這個比較簡單,JavaScript作為解釋性語言,最大的一個特性就是可以随時随地地通過解釋器執行一段JS代碼,是以可以将拼接的JavaScript代碼字元串,傳入JS解析器執行就可以,JS解析器在這裡就是webView。

Web調用Native端主要有兩種方式

4.2.1 攔截Webview請求的URL Schema

<code>URL Schema</code>是類URL的一種請求格式,格式如下:

我們可以自定義JSBridge通信的<code>URL Schema</code>,比如:<code>jsbridge://showToast?text=hello</code>

<code>Native</code>加載<code>WebView</code>之後,Web發送的所有請求都會經過WebView元件,是以Native可以重寫WebView裡的方法,攔截Web發起的請求,我們對請求的格式進行判斷:

如果符合我們自定義的URL Schema,對URL進行解析,拿到相關操作、操作,進而調用原生Native的方法

如果不符合我們自定義的URL Schema,我們直接轉發,請求真正的服務

Web發送URL請求的方法有這麼幾種:

安卓提供了<code>shouldOverrideUrlLoading</code>方法攔截

IOS<code>UIWebView</code>使用<code>shouldStartLoadWithRequest</code>,

IOS<code>WKWebView</code>則使用<code>decidePolicyForNavigationAction</code>

這種方式從早期就存在,相容性很好,但是由于是基于URL的方式,長度受到限制而且不太直覺,資料格式有限制,而且建立請求有時間耗時。

4.2.2 向Webview中注入JS API

這個方法會通過<code>webView</code>提供的接口,App将Native的相關接口注入到<code>JS</code>的<code>Context(window)</code>的對象中,一般來說這個對象内的方法名與Native相關方法名是相同的,Web端就可以直接在全局window下使用這個全局JS對象,進而調用原生端的方法。

Android(4.2+)提供了addJavascriptInterface注入:

在Web端直接調用這個方法即可:

上面已經說到了Native、Web間雙向通信的兩種方法,但站在一端而言還是一個單向通信的過程 ,比如站在Web的角度:Web調用Native的方法,Native直接相關操作但無法将結果傳回給Web,但實際使用中會經常需要将操作的結果傳回,也就是JS回調。

是以在對端操作并傳回結果,有輸入有輸出才是完整的調用,那如何實作呢?

其實基于之前的單向通信就可以實作,我們在一端調用的時候在參數中加一個<code>callbackId</code>标記對應的回調,對端接收到調用請求後,進行實際操作,如果帶有<code>callbackId</code>,對端再進行一次調用,将結果、callbackId回傳回來,這端根據callbackId比對相應的回調,将結果傳入執行就可以了。

實作一個完整的JSBridge是比較複雜的,需要考慮一些低端機型的相容問題、同步異步調用問題,好在已經有開源的JSBridge供我們直接使用了:

DSBridge,主要通過注入API的形式,DSBridge for Android、DSBridge for IOS

JsBridge,主要通過攔截URL Schema,JsBridge

以DSBridge-Android為例:

Hybrid開發是目前移動端開發的主流技術選項,其中Native和Web端的雙向通信就離不開JSBridge 其中Native調用Web端是直接在JS的Context直接執行JS代碼,Web端調用Native端有兩種方法,一種是基于URL Schema的攔截操作,另一種是向JS的Context(window)注入Api,其中注入Api是目前最好的選擇。完整的調用是雙向通信,需要一個回調函數,技術實作上就是使用了兩次單向通信

開源的JSBridge:DSBridge、jsBridge。

作者:前端南玖

出處:https://www.cnblogs.com/songyao666/

-------------------------------------------

個性簽名:智者創造機會,強者把握機會,弱者坐等機會。做一個靈魂有趣的人!

如果覺得這篇文章對你有小小的幫助的話,可以關注下方公衆号,在該公衆号同樣會推送技術文章給大家,謝謝~

歡迎加入前端技術交流群:928029210

聊一聊橋接(JSBridge)的原理

繼續閱讀