一篇文章了解 JsBridge


一篇文章了解 JsBridge文章插图
一 、jsbridge 定义
JSBridge 是一种 JS 实现的 Bridge , 连接着桥两端的 Native 和 H5 。 它在 APP 内方便地让 Native 调用 JS , JS 调用 Native, 是双向通信的通道 。 JSBridge 主要提供了 JS 调用 Native 代码的能力 , 实现原生功能如查看本地相册、打开摄像头、指纹支付等 。
【一篇文章了解 JsBridge】二、JSBridge 用途
JSBridge 就像其名称中的『Bridge』的意义一样 , 是 Native 和非 Native 之间的桥梁 , 它的核心是 构建 Native 和非 Native 间消息通信的通道 , 而且是 双向通信的通道 。
双向通信的通道:
1) JS 向 Native 发送消息: 调用相关功能、通知 Native 当前 JS 的相关状态等 。
2) Native 向 JS 发送消息: 回溯调用结果、消息推送、通知 JS 当前 Native 的状态等 。
H5与Native交互如下图:
一篇文章了解 JsBridge文章插图
三、JSBridge 的实现原理JavaScript 是运行在一个单独的 JS Context 中(例如 , WebView 的 Webkit 引擎、JSCore) 。 由于这些 Context 与原生运行环境的天然隔离 , 我们可以将这种情况与 RPC(Remote Procedure Call , 远程过程调用)通信进行类比 , 将 Native 与 JavaScript 的每次互相调用看做一次 RPC 调用 。
在 JSBridge 的设计中 , 可以把前端看做 RPC 的客户端 , 把 Native 端看做 RPC 的服务器端 , 从而 JSBridge 要实现的主要逻辑就出现了:通信调用(Native 与 JS 通信) 和句柄解析调用 。
四、JSBridge 的通信原理
一、JavaScript 调用 Native的方式
JavaScript 调用 Native 的方式 , 主要有两种:注入 API 和 拦截 URL SCHEME 。
一篇文章了解 JsBridge文章插图
1?注入API注入 API 方式的主要原理是 , 通过 WebView 提供的接口 , 向JavaScript 的 Context(window)中注入对象或者方法 , 让 JavaScript 调用时 , 直接执行相应的 Native 代码逻辑 , 达到 JavaScript 调用 Native 的目的 。
对于 iOS 的 UIWebView , 实例如下:
JSContext *context = [uiWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; context[@"postBridgeMessage"] = ^(NSArray *calls) { // Native 逻辑 }; 前端调用方式: window.postBridgeMessage(message); 2?拦截 URL SCHEME先解释一下 URL SCHEME:URL SCHEME是一种类似于url的链接 , 是为了方便app直接互相调用设计的 , 形式和普通的 url 近似 , 主要区别是 protocol 和 host 一般是自定义的 ,
例如: qunarhy://hy/url?url=ymfe.tech , protocol 是 qunarhy , host 则是 hy 。
拦截 URL SCHEME 的主要流程是:Web 端通过某种方式(例如 iframe.src)发送 URL Scheme 请求 , 之后 Native 拦截到请求并根据 URL SCHEME(包括所带的参数)进行相关操作 。
在时间过程中 , 这种方式有一定的缺陷:
1) 使用 iframe.src 发送 URL SCHEME 会有 url 长度的隐患 。
2) 创建请求 , 需要一定的耗时 , 比注入 API 的方式调用同样的功能 , 耗时会较长 。
因此:JavaScript 调用 Native 推荐使用注入 API 的方式
二、Native 调用 JavaScript 的方式
相比于 JavaScript 调用 Native ,Native 调用 JavaScript 较为简单 , 直接执行拼接好的 JavaScript 代码即可 。
从外部调用 JavaScript 中的方法 , 因此 JavaScript 的方法必须在全局的 window 上 。
对于 iOS 的 UIWebView , 示例如下:
result = [uiWebview stringByEvaluatingJavaScriptFromString:javaScriptString]; * javaScriptString为JavaScript 代码串 对于 iOS 的 WKWebView , 示例如下:
[wkWebView evaluateJavaScript:javaScriptString completionHandler:completionHandler]; 三、通信原理总结通信原理是 JSBridge 实现的核心1)JavaScript 调用 Native 推荐使用 注入 API 的方式(iOS6 忽略 , Android 4.2以下使用 WebViewClient 的 onJsPrompt 方式) 。
2)Native 调用 JavaScript 则直接执行拼接好的 JavaScript 代码即可 。
四、JSBridge 接口实现
JSBridge 的接口主要功能有两个:调用 Native(给 Native 发消息) 和 被 Native 调用(接收 Native 消息) 。 因此 , JSBridge 可以设计如下:
window.JSBridge = {// 调用 Nativeinvoke: function(msg) {// 判断环境 , 获取不同的 nativeBridgenativeBridge.postMessage(msg);},receiveMessage: function(msg) {// 处理 msg} }; 在上面的文章中 , 提到过 RPC 中有一个非常重要的环节是 句柄解析调用, 这点在 JSBridge 中体现为 句柄与功能对应关系 。 同时 , 我们将句柄抽象为 桥名(BridgeName) , 最终演化为 一个 BridgeName 对应一个 Native 功能或者一类 Native 消息 。 基于此点 , JSBridge 的实现可以优化为如下: