Flutter

NativeBridge:基于webivew_flutter的J

2022-11-28  本文已影响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,如有侵权,请联系删除。

上一篇下一篇

猜你喜欢

热点阅读