美文网首页JavaScript
逐行分析WebViewJavascriptBridge源码

逐行分析WebViewJavascriptBridge源码

作者: 赵一鸣的笔记本 | 来源:发表于2019-11-26 10:37 被阅读0次

    最近项目中,把 APP 和 小程序 里 80% 的页面都换成了 H5,目的是快速开发,方便热更新。

    前端除了要保证代码高度复用并且降低耦合,还要主动和负责 Native 开发的同学沟通,定义好协议,留下文档,方便后期维护。

    混合开发,最核心的是数据交互:

    • 小程序端:在不影响用户体验的情况下,直接或间接的使用现有规则进行开发。

    • Native端:使用了目前市面上成熟的 WebViewJavaScriptBridge 开源库。在 Android 端踩了一些坑,iOS 端没出现太大的问题。

    项目完成了,抽时间学习下 WebViewJavaScriptBridge 源码,顺便对这次 Hybrid 开发做下总结。

    JavaScript 与 Native 交互的方式(以iOS为例)

    1、JS 调用 Native 方法:

    • Native 拦截 URL 跳转
    window.location.href = 'Native自定义协议';
    
    • 使用 WebKit,苹果官方推荐使用这种方式
    window.webkit.messagehandlers.<name>.postMessage('xxx');
    

    2、Native 调用 JS 方法

    前端将 JS function 暴露到全局 window 对象上, Native 在 web-view 中注入 JS 代码执行。

    以上方法如果单独使用,都比较麻烦,而且代码难以组织,Native 拦截 URL 跳转或使用 WebKit 更多时候是用在前端单向调用 Native 方法的场景,不支持 return 和 callback,只能做 send 操作,做不了 get 操作。

    3、使用 WebViewJavaScriptBridge 开源库

    iOS 和 Android 对应的代码开源地址:

    iOS WebViewJavascriptBridge

    Android JsBridge

    WebViewJavaScriptBridge 实现机制

    WebViewJavaScriptBridge 很好的解决了 JS 和 Native 通信的问题,并且使我们能更好的组织代码,其原理也是根据以上两种方法做了进一步封装。

    JS 和 Native 需要互相调用,那么各自都需要做到两点:

    1、注册好方法,供对方调用

    2、调用对方已注册的方法

    WebViewJavaScriptBridge交互图.png

    iOS(WKWebView)对外暴露的API:

    - (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler;
    
    - (void)removeHandler:(NSString*)handlerName;
    
    - (void)callHandler:(NSString*)handlerName;
    - (void)callHandler:(NSString*)handlerName data:(id)data;
    - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;
    
    - (void)reset;
    - (void)setWebViewDelegate:(id)webViewDelegate;
    - (void)disableJavscriptAlertBoxSafetyTimeout;
    

    JavaScript 对外暴露的 API:

    window.WebViewJavascriptBridge = {
      registerHandler: registerHandler,
      callHandler: callHandler,
      disableJavscriptAlertBoxSafetyTimeout: disableJavscriptAlertBoxSafetyTimeout,
      _fetchQueue: _fetchQueue,
      _handleMessageFromObjC: _handleMessageFromObjC
    };
    

    我们通常使用的也就是它们各自的 registerHandler 和 callHandler 方法。

    WebViewJavaScriptBridge 目录结构

    1、WebViewJavascriptBridgeBase

    用来进行 bridge 初始化和消息处理的核心类,其保存了三个很重要的属性:

    • responseCallbacks:用于保存 Objective-C 与 javascript 环境相互调用的回调模块。通过 _uniqueId 加上时间戳来确定每个调用的回调。

    • messageHandlers:用于保存 Objective-C 环境注册的方法,key 是方法名,value 是这个方法对应的回调 block

    • startupMessageQueue:保存类实例化过程中需要发送给 JavaScirpt 环境的消息。

    2、WebViewJavascriptBridge

    bridge 入口类,判断当前 WebView 的类型是 UIWebView 或 WKWebView,执行相应的逻辑。

    3、WKWebViewJavascriptBridge

    针对 WKWebView 做的一层封装,主要用来执行 JS 代码,以及实现 WKWebView 的代理方法,并通过拦截 URL 来通知 WebViewJavascriptBridgeBase 做相应操作。本次源码学习,也是以 WKWebViewJavascriptBridge 为主,忽略 UIWebView。

    4、WebViewJavascriptBridge_JS

    其代码会被注入到 WebView 中,用于 JavaScript 端的 register 和 call 操作。

    本次源码(iOS WebViewJavascriptBridge)学习笔记全部记录在 docs 目录下。

    iOS 初始化 WebViewJavascriptBridge

    JavaScript 初始化 Bridge

    JavaScript 主动调用 iOS 方法

    iOS 主动调用 JavaScript 方法

    代码示例全部放在 demo 目录下,包括 JavaScript 和 Objective-C 初始化及具体调用方法。

    bridge.js

    YMBridgeController.m

    相关文章

      网友评论

        本文标题:逐行分析WebViewJavascriptBridge源码

        本文链接:https://www.haomeiwen.com/subject/mmhewctx.html