iscarecrow / myBlog

Think and Write Critically
6 stars 2 forks source link

WebViewJavascriptBridge源码解析及sdk设计 #11

Open iscarecrow opened 7 years ago

iscarecrow commented 7 years ago

内容分为以下几块

1.jssdk介绍

hybird app开发中,为了解决webview内的js调用原生控件,方法等的业务逻辑。需要做一层webview和native的bridge通信。业务开发中iOS选用了WebViewJavascriptBridge这个库,安卓可以使用这个webviewjavascriptbridge。以下对源码进行简单分析

2.WebViewJavascriptBridge源码解析

js调用原生,callhandler

jsbridgedemo1

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和客户端相互调用方法

存在两种业务

4.常用功能设计心得

常用的需要的抽象业务js调用原生
原生调用js

5. 存在的问题



- 新方法需要发布,没有好方法
做好业务抽象

- 如何做版本管理
采用webview的 useragent写入sdk 版本字段。不同版本下进行业务兼容

- 多平台兼容问题
建议写好的jssdk,不要直接调用。 而是针对平台封装一层调用。例:登陆逻辑,调用jssdk.login()。原生弹出原生框。微信采用微信登陆。原生h5可以自己做个登陆框。其他逻辑相同

- 广播方法及可能面临的问题
webview的前进方式采用了打开新的窗口的方式。回退过程无法刷新。所以数据通知采用广播。 但是如果同一个h5需要在非自己app平台呈现。就需要采用其他方式处理。比如localstorage

前端调用bridge demo   [dt-sdk](https://github.com/iscarecrow/dt-sdk)
pplgin commented 7 years ago

厉害了!