美文网首页Flutter
NativeBridge:基于webivew_flutter的J

NativeBridge:基于webivew_flutter的J

作者: 蜗牛是不是牛 | 来源:发表于2022-11-28 21:07 被阅读0次

    前沿

    作为移动端开发,免不了需要内嵌 H5网页 的需求。在 Flutter 中我们一般通过官方的 [webview_flutter]插件实现 WebView 的加载。[webview_flutter]插件是由官方维护,底层通过 WebView / WKWebView 原生组件实现,不管是稳定性还是可靠性上都有保障。但其在与 H5端 的 JSBridge 调用上却差强人意,目前只支持 H5端 到 App端 的单向调用,而且还不能直接获取返回值,这大大限制了我们对于 [webview_flutter]插件的使用。

    为了解决 [webview_flutter]的 JS 调用问题,[NativeBridge] 插件应运而生。

    效果展示

    在介绍插件前,我们先看看集成后的效果:

    image.png

    NativeBridge 插件的优点

    1. 支持 H5端 调用 App端JSBridge 方法,并可以 直接获取返回值
    2. 支持 App端 调用 H5端JSBridge 方法,并可以 直接获取返回值
    3. 使用简单,集成插件后实现 NativeBridgeImpl 类,即可完成 App端JS调用 能力的支持。

    NativeBridge 的引入

    NativeBridge 插件目前支持2种引入方式:1)本地代码引入 2)Git 依赖

    1. 本地代码引入。由于插件本身只引入了 webview_flutter 插件,所以可以直接拷贝相关代码到自己的项目即可。
    2. Git 依赖。目前由于插件还没有发布到 pub ,大家可以先通过 Git 依赖的方式引入。
    dependencies:
      native_bridge:
        git:
          url: https://github.com/Fitem/native_bridge.git
    
    

    NativeBridge 的集成

    1. App端。在 App端,插件的使用非常简单,只需要下面 两步 即可完成。

    第一步,通过 implements NativeBridgeImpl 类,实现其对应的方法。例如 example 中的 NativeBridgeController 类的实现:

    class NativeBridgeController implements NativeBridgeImpl {
      NativeBridgeController({required this.controller});
    
      // WebView控制器
      final Future<WebViewController> controller;
    
      /// 对应JS调用Function集合
      @override
      Map<String, Function?> get callMethodMap => {
            // 版本号
            "getVersionCode": (data) async {
              return await AppUtil.getVersion();
            },
            // 版本名称
            "getVersionName": (data) async {
              return await AppUtil.getVersion();
            },
            //是否是App
            "isApp": (data) {
              return true;
            },
            //测试获取Web的值
            "getWebValue": (data) async {
              var isHome = await NativeBridgeHelper.sendMessage(
                  Message(api: "isHome"), this)
                  .future ??
                  false;
              AppUtil.show("isHome:$isHome");
              return true;
            }
          };
    
      /// 指定JSChannel名称
      @override
      String get name => "nativeBridge";
    
      /// 执行JS
      @override
      void runJavascript(String javaScriptString) {
        controller.then((controller) =>
            controller.runJavascript("receiveMessage($javaScriptString)"));
      }
    }
    
    
    
    1. NativeBridgeController 构造参数传入 WebView 的 Controller 对象,用于 runJavascript 的调用
    2. name 指定 H5 端生成的 window.nativeBridge 对象名称
    3. callMethodMap 定义 App端 可以支持的 JSBridge 方法和调用

    第二步,在 WebView 组件中添加 NativeBridge

    //JS执行模式 是否允许JS执行
    javascriptMode: JavascriptMode.unrestricted,
    javascriptChannels: <JavascriptChannel>{
        NativeBridge(
            controller: _nativeBridgeController =
                 NativeBridgeController(controller: _controller.future),
        )
    }
    
    

    2. H5端。H5端的实现也非常简单,1)引入 jsBridgeHelper.js 文件,2)window 对象添加 *receiveMessage 全局方法用于 App端消息的接收。

    function receiveMessage(jsonStr) {
        if(jsonStr != undefined && jsonStr != "") {
            let data = JSON.parse(JSON.stringify(jsonStr));
            window.jsBridgeHelper.receiveMessage(data);
        }
    }
    
    

    NativeBridge 的使用

    一、H5端 获取 App端 的值

    1. 在 App端 的 callMethodMap 中 定义方法名称Function调用,比如获取 App 的版本号:
    // 版本号
    "getVersionCode": (data) async {
        return await AppUtil.getVersion();
    }
    
    
    1. 在 H5端 中调用对应方法:
    async function getVersionName() {
        // 获取 App 的值
        let appVersionName = await window.jsBridgeHelper.sendMessage("getVersionName", null);
        // 显示
        document.getElementById("app_version_name").innerHTML = "app version name : " + appVersionName.toString();
    }
    
    

    展示效果:

    [图片上传失败...(image-96709f-1669640787874)]

    二、App端 获取 H5端 的值

    1. App端 先调用 sendMessage() 方法:
    var isHome = await NativeBridgeHelper.sendMessage(
                Message(api: "isHome"), _nativeBridgeController,
                ).future ?? false;
    AppUtil.show("isHome:$isHome");
    
    
    1. H5端 在 jsBridgeHelper.js 类中的 receiveMessage() 方法中通过对 message.api 识别,通过 _postMessage() 方法发送App需要获取的值
    receiveMessage(message) {
        if (message.callbackId) {
            // 通过callbackId 获取对应Promise
            const cb = this._popCallback(message.callbackId);
            if (cb) { //有值,则直接调用对应函数
                cb(message.data);
            } else { //没有值,则是App请求获取值
                if (message.api === 'isHome') {
                this._postMessage(message.api, true.toString(), message.callbackId)
            }
            }
        }
    }
    
    

    展示效果:

    [图片上传失败...(image-4024c5-1669640787874)]

    总结

    今天主要介绍了 Flutter 中基于 webview_flutter 插件实现 App端 和 H5端 的 JS 互调能力的插件 NativeBridge,以及 NativeBridge 的集成和使用,下一篇将介绍 NativeBridge 插件的实现原理和超时检测机制,感兴趣的同学可以关注后续文章。

    本文转自 https://juejin.cn/post/7170557198701953038,如有侵权,请联系删除。

    相关文章

      网友评论

        本文标题:NativeBridge:基于webivew_flutter的J

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