导语:以前只简单做过微信小程序的应用开发,却不知道小程序是怎么运行起来了,其实现的原理是什么?
1、什么是JsBridge
在移动开发中,我们讲究尽可能降低开发和更新维护成本,如微信小程序和Weex等都可以一次开发多端运行。究其原理,JavaScript起到了举足轻重的作用,它肩负起了与其他技术桥接的职责,任何一个移动操作系统中都包含可运行 JavaScript 的容器,例如 WebView 和 JSCore,运行 JavaScript 不用像运行其他语言时,要额外添加运行环境。JsBridge正是这样的桥接!
JsBridge给JavaScript提供了调用Native功能,Native也能够操控JavaScript。这样前端部分就可以方便使用地理位置、摄像头以及登录支付等Native能力啦。JSBridge构建 Native和非Native间消息通信的通道,而且是 双向通信的通道。
- JS 向 Native 发送消息 : 调用相关功能、通知 Native 当前 JS 的相关状态等。
- Native 向 JS 发送消息 : 回溯调用结果、消息推送、通知 JS 当前 Native 的状态等。
2、JSBridge的实现原理
JSBridge最根本的原理就是它的通信原理,即如何实现JavaScript与Native之间的双向通信。
2.1 JavaScript调用Native
注入API与拦截URL SCHEME
2.1.1 注入API
通过WebView提供的接口,向JavaScript的运行环境即Context注入对象或者方法,让JavaScript调用时直接执行相应的Native代码逻辑。达到JavaScript调用Native的目的。
以我们所熟知的Android WebView为例
WebView webView=(WebView)findViewById(R.id,webView);
Jscore mJscore=new Jscore();
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(mJscore,“naiveBridge”);
public class Jscore {
@JavascriptInterface
public void postMessage(String webMessage){
// Native 逻辑
}
}
}
其中,mJscore是我们Native的一个对象实例,nativeBridge是运行在当前webview中的一个Js对象,addJavascriptInterface是webview提供给我们注入的接口。这样注入API完成之后,当JS执行nativeBridge的postMessage()方法时会直接执行到Native中Jscore的postMessage方法。
nativeBridge.postMessage(message)
这里需要注意,4.4之后, 需要在调用Java方法加入@JavascriptInterface注解,如果代码无此声明,那么js就不生效,这样就可以避免恶意网页利用js对客户端的进行窃取和攻击
2.1.2 拦截 URL SCHEME
这种方式是Web端通过某种方式发送URLScheme请求,之后Native拦截到请求并根据URL SCHEME(包括所带的参数)进行相关操作。类似于通过SCHEME唤起APP。这种方式的缺点是url长度有隐患,并且创建请求需要一定的耗时,比注入API的方式调用同样的功能。耗时会比较长。所以还是推荐使用注入API的方式。
2.2 Native调用JavaScript
Native调用JavaScript,其实就是执行拼接的JavaScript字符串,从外部调用JavaScript中的方法。
在Android中,4.4之后用webView的evaluateJavaScript方法实现:
webView.evaluateJavascript(javaScriptString, new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
}
});
而在4.4之前使用webView的loadUrl方法来执行JavaScript代码
webView.loadUrl("javascript:" + javaScriptString);
但是这样不能得到JavaScript执行后的结果。
3、JSBridge接口实现
现在我们知道JSBridge能够使得JS调用Native和被Native调用。当然,其不只是这些作用。如果JS要调用很多Native的功能,怎么区分这些不同的功能呢?答案是句柄与功能对应,这里将句柄抽象为桥名(BridgeName),最终演变为一个BridgeName对应一个Native功能或者一类Native消息。其实,我们也可以将这个桥名理解为Native中的方法名,据此来执行不同的Native功能。
接下来我们讨论调用Native功能时的Callback(回调)怎么实现?
既然是要执行特定的Callback,那么我们就要想办法找到对应的Callback,这个办法就是做标记。在Js中用一个自增的唯一id,来标识和存储回调函数,并把这个id以参数形式传递给Native,而Native也以此id作为回溯的标识,既可以实现Callback的回调逻辑。
4、JsBridge的开源库
关于JSBridge的开源库,业界使用最多的是:https://github.com/lzyzsd/JsBridge。 这个不赘述,大家可自行查阅资料,其原理就是我们上面讨论的,只不过对逻辑进行了封装,js和Java都只需要进行注册函数,然后对端就可以进行调用了。
详细参考文献:https://mp.weixin.qq.com/s/I812Cr1_tLGrvIRb9jsg-A