跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Dart大前端

Flutter 中 JavaScript 与 Dart 双向通信实现方案

在 Flutter 项目中实现 JavaScript 与 Dart 双向通信的方案。主要包含基于官方 webview_flutter 插件的通信方式,通过在 pubspec.yaml 添加依赖、配置静态 JS 文件、创建 Dart 交互方法定义及项目启动类配置。同时涵盖了 Web 平台下使用 @JS 注解建立 Dart 与 JS 映射关系,以及利用 @allowInterop 传递 Dart 函数给 JS 作为回调的方法。重点讲解了 postMessage 通道机制、WebViewController 配置及回调处理逻辑。

SqlMaster发布于 2026/3/28更新于 2026/9/1165 浏览
Flutter 中 JavaScript 与 Dart 双向通信实现方案

基于官方 webview_flutter 插件的通信方式

在 pubspec.yaml 中添加

添加 webview 包方便后面使用,记得 pub get 更新。

dependencies: 
  flutter: sdk: flutter # 移动端 WebView 通信核心依赖
  webview_flutter: ^4.4.4 # Web 平台 JS 通信依赖
  js: ^0.6.7

配置自己使用的 js 路径地址信息,该地址位于项目根目录中添加对应 js 文件。

flutter:
  uses-material-design: true
  assets:
    - assets/js/xxx.js

静态 js 文件,建立通道

function test() {
  if (window.FlutterJsChannel) {
    window.FlutterJsChannel.postMessage(realTimeData);
    console.log(realTimeData);
    console.log("【JS 推送成功】:数据已发送给 Flutter");
  } else {
    console.log("【JS 推送失败】:FlutterJsChannel 不存在");
  }
}

postMessage 通道的核心概念:

  • postMessage 本质是 Flutter 为 WebView 提供的跨端通信接口,专门用于 JavaScript → Flutter 的数据传递(单向主动推送)。
  • Flutter 在 WebView 里'预埋'了一个名为 FlutterJsChannel(你自定义的名称)的'消息信箱'。
  • JS 端只要往这个'信箱'里丢消息(调用 postMessage),Flutter 端的 onMessageReceived 回调就会立刻收到并处理。
  • WebView 加载的 HTML/JS 中,通过 window.通道名称.postMessage(数据) 发送消息。

Dart 文件 创建 web 交互 方法定义

通过 runJavaScript(jsCode); 调用项目内部方法。

import 'package:webview_flutter/webview_flutter.dart';

late WebViewController _webViewController;
_webViewController = WebViewController()
  ..setJavaScriptMode(JavaScriptMode.unrestricted)
  ..setBackgroundColor(Colors.white)
  ..loadHtmlString("""<html><body></body></html>""")
  ..addJavaScriptChannel("FlutterJsChannel", // 实时接收 JS 传递的数据(持续回调,无需主动触发)
    onMessageReceived: (JavaScriptMessage message) {
      print("object"); // 第一步:先打印日志,这是最直接的验证,无关 UI 更新
      print("【通道回调触发】:收到数据 -> ${message.message}");
      _updateAnimeList(message.message);
    });

// 步骤 1:读取并加载 Assets 中的 JS 文件(核心:注入 JS 函数)
Future<void> _loadAssetsJsFile() async {
  try {
    // ① 读取 Assets 中的 JS 文件(转为纯文本字符串)
    // 路径必须和 pubspec.yaml 中声明的一致(大小写敏感)
    String assetsJsContent = await rootBundle.loadString("assets/js/md5.js");
    // ② 执行该 JS 字符串,将函数注入 WebView 环境
    // 此时只是「导入」函数,并未调用具体方法,无返回值
    await _webViewController.runJavaScript(assetsJsContent);
    setState(() {
      _callResult = "Assets JS 文件加载完成(函数已注入),可调用具体方法";
      _callAssetsJsFunction();
      print(_callResult);
    });
  } catch (e) {
    setState(() {
      _callResult = "加载 Assets JS 文件失败:$e";
    });
  }
}

// 步骤 2:调用 Assets JS 文件中定义的具体方法
_callAssetsJsFunction() async {
  try {
    // ① 编写 JS 代码,调用已注入的函数(来自 assets/js/demo.js)
    String jsCode = """ test(); """;
    // ③ 执行 JS 代码,触发函数调用
    _webViewController.runJavaScript(jsCode);
    print("【Flutter】JS 执行指令已发送给 WebView");
  } catch (e) {
    setState(() {
      _callResult = "调用 Assets JS 函数失败:$e";
    });
  }
}
  • WebViewController():创建一个 WebView 的控制器实例,用来管理 WebView 的所有行为(加载页面、JS 交互、样式设置等)。
  • setJavaScriptMode(JavaScriptMode.unrestricted):开启 WebView 的 JavaScript 支持。JavaScriptMode.unrestricted:完全允许 JS 执行(默认是禁用的),这是 Flutter 和 JS 交互的前提。如果设为 JavaScriptMode.disabled,则 WebView 中的 JS 代码无法运行,通信通道也会失效。
  • setBackgroundColor(Colors.white):设置 WebView 的背景颜色为白色(默认可能是透明或灰色),优化视觉效果。
  • loadHtmlString(...):加载一段空的 HTML 字符串到 WebView 中(也可以用 loadUrl 加载远程网页)。这里加载空页面,说明核心目的是通过 JS 通道接收数据,而非展示网页内容。
  • addJavaScriptChannel(...):这是核心逻辑:创建 Flutter 和 JS 之间的通信通道,实现 JS 主动向 Flutter 发送数据。
    • 'FlutterJsChannel':通道的唯一标识,JS 端必须通过这个名称调用(比如 window.FlutterJsChannel.postMessage('要传递的数据'))。
    • onMessageReceived:回调函数,只要 JS 调用了 postMessage,这个回调就会实时触发(也就是你注释里说的'持续回调,无需主动触发')。
    • JavaScriptMessage message:回调的参数,message.message 是 JS 传递的原始数据(字符串类型)。
  • 回调内的逻辑:
    • print(...):打印 JS 传递的数据,用于调试验证。
    • _updateAnimeList(message.message):调用自定义方法处理数据(比如解析数据、更新动漫列表)。
    • 注释的 setState:如果需要更新 Flutter 的 UI(比如把数据展示在页面上),必须用 setState 触发页面刷新。

项目启动类

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

WidgetsFlutterBinding.ensureInitialized() 是 Flutter 应用的'基础引擎初始化',为所有 Widget 和异步操作提供运行环境。

Web 平台 - Dart 与 JS 通信

@JS

@JS() 是 package:js 库提供的元注解(装饰器),作用是建立 Dart 代码和 JS 代码的映射关系。你可以把它理解成:给 Dart 代码贴一个'标签',告诉 Dart 编译器'这段代码要对应到 JS 中的某个东西'。

传递 Dart 函数给 JS(回调)

用 @allowInterop 注解(@JS() 配套),可以把 Dart 函数作为回调传给 JS。

  • @JS() 是 Dart 与 Web 端 JS 交互的核心注解,用于建立 Dart 代码和 JS 变量 / 函数 / 对象的映射关系。
  • 使用时必须导入 package:js,且被注解的成员需加 external 关键字。
  • 配套 @allowInterop 可实现 Dart 函数作为回调传给 JS,仅支持 Web 平台。

目录

  1. 基于官方 webview_flutter 插件的通信方式
  2. 在 pubspec.yaml 中添加
  3. 静态 js 文件,建立通道
  4. Dart 文件 创建 web 交互 方法定义
  5. 项目启动类
  6. Web 平台 - Dart 与 JS 通信
  7. @JS
  8. 传递 Dart 函数给 JS(回调)

更多推荐文章

查看全部
  • Stable Diffusion 模型原理与本地部署实战
  • Windows 环境下 Clawdbot Gateway 持久化运行配置指南
  • K-means 聚类算法原理与实现详解
  • 户外机器人 GNSS 仿真测试方案:实现高精度定位与双天线定向
  • 使用 Doubao-Seed-Code 优化 Unity 编辑器插件:从功能实现到界面美化
  • C++ 协程深度解析:从内部机制到实用场景
  • C++ STL 有序关联容器详解:set、map 及其变体用法
  • LeetCode 202. 快乐数:快慢指针解法详解
  • Llama Factory 微调实战:优化截断长度解决显存溢出
  • Spring Boot 4.0 核心新特性解析与实操指南
  • M977.7CC:AI 辅助生成高性能代码实践
  • Harness Engineering 工程化教程:AI Agent 复杂长任务实践指南
  • Flutter webrtc_interface 鸿蒙化适配与实战指南
  • C++ 智能指针:使用场景、实现原理与内存泄漏防治
  • 鸿蒙金融理财应用:架构设计、安全与体验优化
  • PostgreSQL 企业级用户画像与行为分析实战:替代 MySQL+Hive 方案
  • Miniforge 在 macOS 和 Windows 上的安装与配置指南
  • ToDesk 内置 ToClaw AI 实现科技新闻日报自动化实战
  • Spring Boot RESTful API 开发、测试与安全认证实战
  • AI 绘画技术解析:GPU 算力租赁如何重塑数字艺术创作

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online