-
Notifications
You must be signed in to change notification settings - Fork 2
Description
内容分为以下几块
- jsbridge介绍
- WebViewJavascriptBridge源码解析
- js和客户端相互调用方法
- 常用功能设计心得
- 存在的问题
1.jssdk介绍
hybird app开发中,为了解决webview内的js调用原生控件,方法等的业务逻辑。需要做一层webview和native的bridge通信。业务开发中iOS选用了WebViewJavascriptBridge这个库,安卓可以使用这个webviewjavascriptbridge。以下对源码进行简单分析
2.WebViewJavascriptBridge源码解析
js调用原生,callhandler
bridge对外提供的方法
window.WebViewJavascriptBridge = {
init: init,
send: send,
// js 调用,注册原生可调用方法
registerHandler: registerHandler,
// js 调用原生,调用方法
callHandler: callHandler,
//native会调用
_fetchQueue: _fetchQueue,
//native会调用
_handleMessageFromObjC: _handleMessageFromObjC
};
sendMessageQueue队列, js调用Native时,包含方法名和数据还有回调函数key的队列,Native 通过此方法_fetchQueue获取
var sendMessageQueue = [];
// handleName每次新的方法都有客户端方法对应。
var obj = {
handlerName:handlerName,
data:data,
callbackId: callbackId
}
回调的所有方法对象responseCallbacks , iOS通过 _dispatchMessageFromObjC消费
// js调用原生的回调方法对象。 每次调用时生成唯一的callbackId的key。
var responseCallbacks = {};
// unique key
var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime();
// 对应的 callback
responseCallbacks[callbackId] = responseCallback;
// native回调
messageJSON = {
responseId: callbackId,
responseData: responseData
}
实际上真正发起调用的地方,iOS采用iframe处理。 安卓的webview可以直接调用js方法。
// iOS调用,采用iframe发起请求的方式
messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE
- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener
{
// iOS 在此拦截了webview发起的请求。
}
原生调用js, registerHandler
messageHandlers, 告诉Native有哪些js方法可以调用,通过registerHandler注册。handleName做为key查找。通过_dispatchMessageFromObjC调用
var messageHandlers = {};
messageHandlers[handlerName] = handler;
此处当时只做了一个注册。(忘记原因了)结果如下:
bridge.registerHandler("_callNavtiveHandler", function(response) {
var method = response.method || '';
var params = response.params;
switch (method) {
case 'A':
BdoA();
break;
case 'B':
doB();
break;
case 'C':
doC();
break;
case 'D':
doD();
break;
default:
}
});
3.js和客户端相互调用方法
存在两种业务
- js调用原生
callHandler,客户端解析handleName 处理即可 - 原生调用js
registerHandler,回调信息中response对象含有name。区分处理即可
4.常用功能设计心得
常用的需要的抽象业务js调用原生
- 弹框,掉卡。采用掉落webview。灵活
- 原生登陆窗。 统一webview的session管理
- 是否登陆
- 原生支付,让客户端对接微信,支付宝等第三方sdk
- 分享组件。 h5分享到第三方平台属于标准业务
- 发布,收藏,选择地址等流程型的抽象逻辑。例选择地址流程。js调用后完全不关心之后的交互流程。只需要拿到地址信息的回调数据
- 放大,轮播等组件类型封装
- 客户端的http请求库。 统一请求库
- 关闭当前页面
- 打开页面,可选择带数据打开
- 客户端打点
- 设备信息
- 设置导航栏
原生调用js
- 广播逻辑,若采用打开新的webview前进的方式。需要广播进行数据同步
- 导航栏点击
5. 存在的问题
- iOS window下的对象挂载时间问题。 webview需要等到资源全部加载完成才开始挂载。
解决方案: 写一个ready方法
sdk.ready = function(callback) {
if (window.WebViewJavascriptBridge) {
callback();
} else {
document.addEventListener('WebViewJavascriptBridgeReady', function() {
callback();
}, false);
}
};
-
新方法需要发布,没有好方法
做好业务抽象 -
如何做版本管理
采用webview的 useragent写入sdk 版本字段。不同版本下进行业务兼容 -
多平台兼容问题
建议写好的jssdk,不要直接调用。 而是针对平台封装一层调用。例:登陆逻辑,调用jssdk.login()。原生弹出原生框。微信采用微信登陆。原生h5可以自己做个登陆框。其他逻辑相同 -
广播方法及可能面临的问题
webview的前进方式采用了打开新的窗口的方式。回退过程无法刷新。所以数据通知采用广播。 但是如果同一个h5需要在非自己app平台呈现。就需要采用其他方式处理。比如localstorage
前端调用bridge demo dt-sdk
