Open iscarecrow opened 7 years ago
hybird app开发中,为了解决webview内的js调用原生控件,方法等的业务逻辑。需要做一层webview和native的bridge通信。业务开发中iOS选用了WebViewJavascriptBridge这个库,安卓可以使用这个webviewjavascriptbridge。以下对源码进行简单分析
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获取
sendMessageQueue
_fetchQueue
var sendMessageQueue = []; // handleName每次新的方法都有客户端方法对应。 var obj = { handlerName:handlerName, data:data, callbackId: callbackId }
回调的所有方法对象responseCallbacks , iOS通过 _dispatchMessageFromObjC消费
responseCallbacks
_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发起的请求。 }
messageHandlers, 告诉Native有哪些js方法可以调用,通过registerHandler注册。handleName做为key查找。通过_dispatchMessageFromObjC调用
messageHandlers
registerHandler
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: } });
存在两种业务
callHandler
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](https://github.com/iscarecrow/dt-sdk)
厉害了!
内容分为以下几块
1.jssdk介绍
hybird app开发中,为了解决webview内的js调用原生控件,方法等的业务逻辑。需要做一层webview和native的bridge通信。业务开发中iOS选用了WebViewJavascriptBridge这个库,安卓可以使用这个webviewjavascriptbridge。以下对源码进行简单分析
2.WebViewJavascriptBridge源码解析
js调用原生,callhandler
bridge对外提供的方法
sendMessageQueue
队列, js调用Native时,包含方法名和数据还有回调函数key的队列,Native 通过此方法_fetchQueue
获取回调的所有方法对象
responseCallbacks
, iOS通过_dispatchMessageFromObjC
消费实际上真正发起调用的地方,iOS采用iframe处理。 安卓的webview可以直接调用js方法。
原生调用js, registerHandler
messageHandlers
, 告诉Native有哪些js方法可以调用,通过registerHandler
注册。handleName做为key查找。通过_dispatchMessageFromObjC
调用此处当时只做了一个注册。(忘记原因了)结果如下:
3.js和客户端相互调用方法
存在两种业务
callHandler
,客户端解析handleName 处理即可registerHandler
,回调信息中response对象含有name。区分处理即可4.常用功能设计心得
常用的需要的抽象业务js调用原生
原生调用js
5. 存在的问题