Flutter跨平台开发鸿蒙化JS-Dart通信桥接组件使用指南

1. 插件介绍

JS-Dart通信桥接组件是一个专为OpenHarmony平台优化的Flutter插件,用于实现JavaScript(WebView)与Dart(Flutter)之间的双向通信。该组件提供了一套完整的通信机制,支持异步调用、回调处理和错误管理,适用于需要在Flutter应用中嵌入Web内容并实现复杂交互的场景。

核心功能

  • 支持JS调用Dart方法并获取返回值
  • 支持Dart调用JS方法并获取返回值
  • 提供异步通信机制
  • 完整的错误处理流程
  • 支持参数和返回值的序列化与反序列化
  • 与OpenHarmony WebView完美集成

2. 环境设置

在使用该组件之前,需要确保开发环境满足以下要求:

Flutter环境

  • Flutter SDK: ≥2.19.6
  • Dart SDK: ≥2.19.6

OpenHarmony环境

  • OpenHarmony SDK API: ≥9
  • DevEco Studio: ≥3.0

项目配置

确保项目已正确配置OpenHarmony开发环境,并已创建Flutter for OpenHarmony项目。

3. 包的引入

由于该组件是自定义修改版本,需要以git形式通过AtomGit引入。在项目的pubspec.yaml文件中添加以下依赖:

yaml 复制代码
dependencies:
  flutter:
    sdk: flutter

  webview_flutter:
    git:
      url: "https://atomgit.com/openharmony-tpc/flutter_packages.git"
      path: "packages/webview_flutter/webview_flutter"

然后运行以下命令安装依赖:

bash 复制代码
flutter pub get

4. API调用与使用示例

4.1 WebView初始化

首先,需要初始化WebView并配置JavaScript支持:

dart 复制代码
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'js_bridge.dart';

class WebPage extends StatefulWidget {
  const WebPage({Key? key}) : super(key: key);

  @override
  State<WebPage> createState() => _WebPageState();
}

class _WebPageState extends State<WebPage> {
  late WebViewController controller;
  final JSBridge _jsBridge = JSBridge();

  @override
  void initState() {
    super.initState();
    _initWebView();
    _initJsBridge();

    Future.delayed(const Duration(seconds: 1), () {
      controller.loadFlutterAsset("assets/html/index.html");
    });
  }

  _initWebView() async {
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..addJavaScriptChannel(
        JSBridge.name,
        onMessageReceived: (JavaScriptMessage message) {
          _jsBridge.receiverMessage(message.message);
        },
      )
      ..setNavigationDelegate(NavigationDelegate(
        onUrlChange: (change) {
          _jsBridge.injectBridgeJS(controller);
        },
      ));
  }

  _initJsBridge() {
    _jsBridge.messageExecutor = controller.runJavaScript;

    // 注册Dart方法供JS调用
    _jsBridge.register("getToken", (data, callback) {
      print("JS调用了getToken方法,参数:$data");
      // 模拟异步操作
      Future.delayed(const Duration(seconds: 1), () {
        callback("flutter_token_123"); // 返回结果给JS
      });
    });
  }

  // 其他代码...
}

4.2 JS调用Dart方法

在HTML页面中,通过注入的bridge对象调用Dart方法:

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
</head>
<body>
    <p id="demo">WebView Content</p>
    <button type="button" onclick="jsCallAsync()">调用Dart方法</button>

    <script>
        async function jsCallAsync() {
            var param = { "userId": "12345" };
            let result = await window.bridge.call("getToken", param);
            document.getElementById("demo").innerHTML = "从Dart获取的Token: " + result;
        }
    </script>
</body>
</html>

4.3 Dart调用JS方法

在Dart代码中,通过JSBridge调用JS方法:

dart 复制代码
_callJsMethod() {
  var param = {"userName": "flutter_user"};
  _jsBridge.call(
    "userInfo",
    param,
    callback: (responseData) {
      print("JS返回结果: $responseData");
      setState(() {
        message = "JS返回结果: $responseData";
      });
    },
    errorCallback: (errorMessage) {
      print("调用JS方法出错: $errorMessage");
    },
  );
}

4.4 JS注册方法供Dart调用

在JS代码中注册方法供Dart调用:

javascript 复制代码
// 注册JS方法
window.bridge.register("userInfo", function(data, callback) {
    console.log("Dart调用了userInfo方法,参数:", data);
    var result = { "name": "JS User", "id": "js_123" };
    callback(result); // 返回结果给Dart
});

5. 资源配置

5.1 添加本地HTML和JS文件

将HTML和JS文件放在项目的assets目录下:

复制代码
assets/
├── html/
│   └── index.html
└── js/
    └── bridge.js

5.2 配置pubspec.yaml

pubspec.yaml文件中配置资源路径:

yaml 复制代码
flutter:
  assets:
    - assets/html/
    - assets/js/

5.3 OpenHarmony权限配置

ohos/entry/src/main/module.json5文件中添加网络权限(如果需要加载远程内容):

json5 复制代码
{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "...",
    "mainElement": "...",
    "deviceTypes": ["phone", "tablet"],
    "distro": {
      "deliveryWithInstall": true,
      "moduleName": "entry",
      "moduleType": "entry"
    },
    "abilities": [...],
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ]
  }
}

6. 完整示例

6.1 Dart端完整代码

dart 复制代码
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'js_bridge.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'JS-Dart Bridge Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const WebPage(),
    );
  }
}

class WebPage extends StatefulWidget {
  const WebPage({Key? key}) : super(key: key);

  @override
  State<WebPage> createState() => _WebPageState();
}

class _WebPageState extends State<WebPage> {
  late WebViewController controller;
  String message = "初始化中...";
  final JSBridge _jsBridge = JSBridge();

  @override
  void initState() {
    super.initState();
    _initWebView();
    _initJsBridge();

    Future.delayed(const Duration(seconds: 1), () {
      controller.loadFlutterAsset("assets/html/index.html");
    });
  }

  _initWebView() async {
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..addJavaScriptChannel(
        "flutterObj",
        onMessageReceived: (JavaScriptMessage message) {
          setState(() {
            this.message = message.message;
          });
        },
      )
      ..addJavaScriptChannel(
        JSBridge.name,
        onMessageReceived: (JavaScriptMessage message) {
          _jsBridge.receiverMessage(message.message);
        },
      )
      ..setNavigationDelegate(NavigationDelegate(
        onUrlChange: (change) {
          _jsBridge.injectBridgeJS(controller);
        },
      ));
  }

  _initJsBridge() {
    _jsBridge.messageExecutor = controller.runJavaScript;

    _jsBridge.register("getToken", (data, callback) {
      print("JS调用了getToken方法,参数:$data");
      Future.delayed(const Duration(seconds: 1), () {
        callback("flutter_token_123");
      });
    });

    _jsBridge.register("testCallback", (data, callback) {
      print("JS调用了testCallback方法,参数:$data");
    });
  }

  _callJsBridge() {
    var param = {"userName": "flutter_user"};
    _jsBridge.call(
      "userInfo",
      param,
      callback: (responseData) {
        setState(() {
          message = "JS返回结果: $responseData";
        });
      },
      errorCallback: (errorMessage) {
        setState(() {
          message = "调用JS方法出错: $errorMessage";
        });
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('JS-Dart Bridge Demo')),
      body: Column(children: [
        ElevatedButton(
          onPressed: () => _callJsBridge(),
          child: const Text("调用JS方法"),
        ),
        Text(message),
        Expanded(
          child: WebViewWidget(controller: controller),
        )
      ]),
    );
  }
}

6.2 HTML端完整代码

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
</head>
<body>
    <p id="demo">WebView Content</p>
    <button type="button" onclick="callFlutterFunction()">发送消息给Flutter</button>
    <button type="button" onclick="jsCallAsync()">调用Dart方法</button>

    <script>
        var count = 0;

        function callFlutterFunction() {
            flutterObj.postMessage('JS 调用了 Flutter ' + (++count));
        }

        async function jsCallAsync() {
            var param = { "userId": "12345" };
            let result = await window.bridge.call("getToken", param);
            document.getElementById("demo").innerHTML = "从Dart获取的Token: " + result;
        }

        // 注册JS方法供Dart调用
        window.bridge.register("userInfo", function(data, callback) {
            console.log("Dart调用了userInfo方法,参数:", data);
            var result = { "name": "JS User", "id": "js_123" };
            callback(result);
        });
    </script>
</body>
</html>

7. 总结

JS-Dart通信桥接组件为OpenHarmony平台上的Flutter应用提供了强大的WebView与Flutter通信能力。该组件支持双向通信、异步调用、回调处理和错误管理,适用于需要在Flutter应用中嵌入Web内容并实现复杂交互的场景。

通过本指南,您可以快速了解该组件的使用方法,包括环境设置、包的引入、API调用和完整示例。该组件已经过OpenHarmony平台优化,确保在OpenHarmony设备上稳定运行。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

相关推荐
Hilaku2 小时前
当 Gemini 3 能写出完美 CSS 时,前端工程师剩下的核心竞争力是什么?
前端·javascript·ai编程
DigitalOcean2 小时前
加速 JavaScript 开发:DigitalOcean 应用托管现已原生支持 Bun
javascript
御承扬3 小时前
鸿蒙原生系列之动画效果(关键帧动画)
华为·harmonyos·鸿蒙ndk ui·关键帧动画
用户6802659051193 小时前
如何利用 Endpoint Central 提高企业终端管理效率
javascript·后端·面试
Keya3 小时前
DevEco Studio 使用技巧全面解析
前端·前端框架·harmonyos
咖啡の猫4 小时前
TypeScript 开发环境搭建
前端·javascript·typescript
前端世界4 小时前
HarmonyOS 应用启动太慢?一套实战方案把首屏时间压下来
华为·harmonyos
是你的小橘呀4 小时前
单页应用路由怎么搞?React Router 从原理到实战全解析!
前端·javascript
风止何安啊4 小时前
Set/Map+Weak三剑客的骚操作:JS 界的 “去重王者” ,“万能钥匙”和“隐形清洁工”
前端·javascript·面试