DSBridge是目前地球上最好的IOS/Android javascript bridge.
DSBridge-IOS:https://github.com/wendux/DSBridge-IOS
DSBridge-Android:https://github.com/wendux/DSBridge-Android
與WebViewJavascriptBridge的對(duì)比請(qǐng)移步 DSBridge VS WebViewJavascriptBridge
DSBridge名稱的由來(lái):DSBridge是DSpider項(xiàng)目使用的 javascript bridge, 分離自
五分鐘了解DSBridge
Web端
假設(shè)Native端實(shí)現(xiàn)了兩個(gè)api: testSyn、testAsyn。參數(shù)以json傳遞诗充, testSyn為同步api,執(zhí)行結(jié)束后會(huì)直接返回結(jié)果朝刊,而testAsyn為一個(gè)異步api(可能會(huì)執(zhí)行耗時(shí)操作)程储,執(zhí)行結(jié)束后配喳,結(jié)果異步返回憔狞。下面我們看看web端如何調(diào)用蹂安。
Javascript調(diào)用Native
var bridge = getJsBridge();
var str=bridge.call("testSyn", {msg: "testSyn"});
bridge.call("testAsyn", {msg: "testAsyn"}, function (v) {
alert(v);
})
簡(jiǎn)單到不用解釋?zhuān)√珒?yōu)雅了椭迎。如果你體會(huì)不來(lái),你也許應(yīng)該去看看當(dāng)今(馬上將會(huì)成為歷史)人氣最高的WebViewJavascriptBridge 田盈,相信你看完之后會(huì)回來(lái)的畜号。雖說(shuō)簡(jiǎn)單,但為了讓你了然于胸允瞧,還是給出官方解釋?zhuān)?/p>
getJsBridge
功能:獲取javascript bridge對(duì)象简软。
等等,貌似和我之前使用的其他庫(kù)不一樣述暂,難道不需要像WebViewJavascriptBridge那樣先聲明一個(gè)setupWebViewJavascriptBridge的回調(diào)痹升?你有這種疑問(wèn)很正常,先給出答案:不需要畦韭,DSBridge不需要前端任何安裝代碼疼蛾,隨用隨取。DSBridge的設(shè)計(jì)原則就是:讓三端使用方式都是最簡(jiǎn)單的艺配! DSBridge獲取bridge時(shí)察郁,不依賴任何回調(diào),也無(wú)需等待頁(yè)面加載結(jié)束转唉。ps: 這在ios>=8,android>sdk19上測(cè)試都沒(méi)問(wèn)題皮钠, DSBridge也對(duì)ios7.0-8.0,android sdk16-19之間的版本做了兼容,但是考慮到測(cè)試覆蓋面的問(wèn)題赠法,建議所有代碼都在dom ready之后執(zhí)行麦轰。
bridge.call(method,[args,callback])
功能:調(diào)用Native api
method: api函數(shù)名
args:參數(shù),類(lèi)型:json, 可選參數(shù)
callback(String returnValue):僅調(diào)用異步api時(shí)需要.
同步調(diào)用
如果你是一名經(jīng)驗(yàn)豐富的開(kāi)發(fā)者砖织,想必看到第二行時(shí)已然眼睛一亮原朝,想想node最被詬病的是什么,目前跨平臺(tái)的jsbridge中沒(méi)有一個(gè)能支持同步镶苞,所有需要獲取值的調(diào)用都必須傳一個(gè)回調(diào)喳坠,如果調(diào)用邏輯比較復(fù)雜,必將會(huì)出現(xiàn)“callback hell”茂蚓。然而壕鹉,DSBridge徹底改變了這一點(diǎn)剃幌。支持同步是DSBridge的最大亮點(diǎn)之一。
異步調(diào)用
對(duì)于一些比較耗時(shí)的api, DSBridge提供了異步支持晾浴,正如上例第三行代碼所示负乡,此時(shí)你需要傳一個(gè)回調(diào)(如果沒(méi)有參數(shù),回調(diào)可作為第二個(gè)參數(shù))脊凰,當(dāng)api完成時(shí)回調(diào)將會(huì)被調(diào)用抖棘,結(jié)果以字符串的形式傳遞。
供Native調(diào)用Javascript api
假設(shè)網(wǎng)頁(yè)中要提供一個(gè)函數(shù)test供native調(diào)用狸涌,只要將函數(shù)聲明為全局函數(shù)即可:
function test(arg1,arg2){
return arg1+arg2;
}
如果你的代碼是在一個(gè)閉包中切省,將函數(shù)掛在window上即可:
window.test=function(arg1,arg2){
return arg1+arg2;
}
這樣一來(lái)端上即可調(diào)用。
Android端
實(shí)現(xiàn)Api
API的實(shí)現(xiàn)非常簡(jiǎn)單帕胆,只需要將您要暴漏給js的api放在一個(gè)類(lèi)中朝捆,然后統(tǒng)一注冊(cè)即可。
public class JsApi{
@JavascriptInterface
String testSyn(JSONObject jsonObject) throws JSONException {
return jsonObject.getString("msg") + "[syn call]";
}
@JavascriptInterface
void testAsyn(JSONObject jsonObject, CompletionHandler handler) throws JSONException {
handler.complete(jsonObject.getString("msg")+" [asyn call]");
}
}
testSyn為同步api, js在調(diào)用同步api時(shí)會(huì)等待native返回懒豹,返回后js繼續(xù)往下執(zhí)行芙盘。
testAsyn為異步api, 異步操作時(shí)調(diào)用handler.complete通知js,此時(shí)js中設(shè)置的回調(diào)將會(huì)被調(diào)用脸秽。
為了安全起見(jiàn)儒老,所有可供js調(diào)用的api必須添加@JavascriptInterface標(biāo)注
注冊(cè)Api
DWebView webView= (DWebView) findViewById(R.id.webview);
webView.setJavascriptInterface(new JsApi());
webView.loadUrl("xx");
請(qǐng)使用sdk中的DWebView,它在實(shí)現(xiàn)了js bridge的同時(shí)记餐,還提供了一些其它的api.
第二句即為注冊(cè)代碼驮樊。
調(diào)用Javascript
DWebView提供了三個(gè)api用于調(diào)用js
void callHandler(String method, Object[] args)
void callHandler(String method, Object[] args, CompletionHandler handler)
void evaluateJavascript(String script)
前兩個(gè)api中,method 為函數(shù)名剥扣,args為參數(shù)數(shù)組巩剖,可以接受String 铝穷、int 钠怯、long、float曙聂、double等晦炊。
第一個(gè)api用于調(diào)用沒(méi)有返回值的js函數(shù),沒(méi)有參數(shù)時(shí)傳null即可宁脊。
第二個(gè)api用于需要返回值的場(chǎng)景断国,需要傳遞一個(gè)CompletionHandler接口對(duì)象,在complete(String returnValue)方法中處理返回值即可榆苞。
第三個(gè)api用于執(zhí)行任意js代碼稳衬,內(nèi)部已做版本兼容處理。
調(diào)用時(shí)機(jī)
DWebview只有在javascript context初始化成功后才能正確執(zhí)行js代碼坐漏,而javascript context初始化完成的時(shí)機(jī)一般都比整個(gè)頁(yè)面加載完畢要早薄疚,隨然DSBridge能捕獲到j(luò)avascript context初始化完成的時(shí)機(jī)碧信,但是一些js api可能聲明在頁(yè)面尾部,甚至單獨(dú)的js文件中(請(qǐng)務(wù)必不要這么做)街夭,如果在javascript context剛初始化完成就調(diào)用js api, 此時(shí)js api 可能還沒(méi)有加載砰碴,所以會(huì)失敗,綜上所述板丽,如果是客戶端主動(dòng)調(diào)用 js應(yīng)該在onPageFinished后調(diào)用呈枉。簡(jiǎn)單的示例如下:
webView.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//期望返回值
webView.callHandler("test",new Object[]{1,"hello"},new CompletionHandler(){
@Override
public void complete(String retValue) {
Log.d("jsbridge","call succeed,return value is "+retValue);
}
});
//不期望返回值
webView.callHandler("test",null);
}
});
DWebview更多
DWebview中下列函數(shù)會(huì)在主線程中執(zhí)行,您不必在手動(dòng)切換線程
void loadUrl( String url)
void loadUrl(final String url, Map<String, String> additionalHttpHeaders)
void evaluateJavascript(String script)
DWebview已經(jīng)實(shí)現(xiàn) alert埃碱、prompt猖辫、comfirm對(duì)話框,您可以不做處理乃正,也可以自定義住册。值得一提的是js 在調(diào)用alert函數(shù)正常情況下只要用戶沒(méi)有關(guān)閉alert對(duì)話框,js代碼是會(huì)阻塞的瓮具,但是考慮到alert 對(duì)話框只有一個(gè)確定按鈕荧飞,也就是說(shuō)無(wú)論用戶關(guān)閉還是確定都不會(huì)影響js代碼流程,所以DWebview中在彈出alert對(duì)話框時(shí)會(huì)先給js返回名党,這樣一來(lái)js就可以繼續(xù)執(zhí)行叹阔,而提示框等用戶關(guān)閉時(shí)在關(guān)閉即可。如果你就是想要阻塞的alert传睹,可以自定義耳幢。而DWebview的prompt、comfirm實(shí)現(xiàn)完全符合ecma標(biāo)準(zhǔn)欧啤,都是阻塞的睛藻。
補(bǔ)充:拉票了,如果你喜歡邢隧,歡迎去github star一下店印,頂一下哦,多謝支持倒慧! https://github.com/wendux/DSBridge-Android