You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter WebView实现FlutterChannel.postMessage的Promise式回调方案

跨平台WebView双向通信实现Promise式回调方案(Android/iOS)

针对你需要在FlutterChannel.postMessage调用后直接用类似Promise.then的方式获取原生结果的需求,我们可以通过请求唯一标识+回调暂存的方式实现,完全适配Android/iOS平台,无需依赖Web专属库。

核心思路

给每个从JS发往Flutter的请求分配唯一ID,在JS端把Promise的resolve函数暂存在全局对象中;Flutter处理完原生逻辑后,携带该ID和结果调用JS的全局处理函数,由JS根据ID找到对应的resolve并执行,以此实现链式回调。


Flutter端代码修改

import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';

// 初始化WebViewController
controller = WebViewController()
  ..setJavaScriptMode(JavaScriptMode.unrestricted)
  ..addJavaScriptChannel('FlutterChannel',
      onMessageReceived: (JavaScriptMessage message) async {
        // 解析JS传来的请求数据(包含唯一ID和业务参数)
        final Map<String, dynamic> requestData = jsonDecode(message.message);
        final String requestId = requestData['requestId'];
        final Map<String, dynamic> payload = requestData['payload'];

        dynamic result;
        try {
          // 根据业务参数执行原生操作(这里以SharedPref为例)
          if (payload['plugin'] == 'SharedPref' && payload['method'] == 'fetch') {
            final String key = payload['params'][0]['key'];
            final prefs = await SharedPreferences.getInstance();
            result = prefs.getString(key);
          }
          // 可扩展其他插件/方法的处理逻辑
        } catch (e) {
          // 捕获异常,返回错误信息
          result = {'error': e.toString()};
        }

        // 将结果和请求ID传回JS,触发对应Promise回调
        await controller.runJavaScript('''
          window.handleFlutterResponse('$requestId', ${jsonEncode(result)});
        ''');
      })
  ..loadRequest(Uri.parse('https://demo.com/'));

JavaScript端代码修改

// 全局对象,用于暂存每个请求的Promise resolve函数(key为请求ID)
window.flutterCallbacks = {};

// 生成唯一请求ID的工具函数
function generateRequestId() {
  return 'req_' + Date.now() + '_' + Math.random().toString(36).slice(2, 11);
}

// 封装调用Flutter的方法,返回Promise
function callFlutter(payload) {
  return new Promise((resolve) => {
    const requestId = generateRequestId();
    // 暂存当前请求的resolve函数
    window.flutterCallbacks[requestId] = resolve;
    // 向Flutter发送包含ID和业务数据的消息
    FlutterChannel.postMessage(JSON.stringify({
      requestId: requestId,
      payload: payload
    }));
  });
}

// Flutter端调用的全局函数,用于触发Promise回调
window.handleFlutterResponse = function(requestId, result) {
  const resolve = window.flutterCallbacks[requestId];
  if (resolve) {
    resolve(result);
    // 执行完回调后删除缓存,避免内存泄漏
    delete window.flutterCallbacks[requestId];
  }
};

// 调用示例(直接用async/await或.then处理结果)
async function fetchSharedPref() {
  const params = {'key':'alternate_preference','value': ''}; 
  const data = { plugin: 'SharedPref', method: 'fetch', params: [params] };
  
  try {
    // 直接等待Flutter返回结果,无需单独定义全局处理函数
    const flutterResult = await callFlutter(data);
    console.log('原生返回结果:', flutterResult);
    // 这里可以直接处理结果,比如更新UI等
  } catch (error) {
    console.error('请求失败:', error);
  }
}

// 触发测试调用
fetchSharedPref();

关键优势

  1. 完全跨平台:适配Android/iOS,无需使用dart:js_interop或dart:html等Web专属API
  2. Promise风格调用:支持async/await和.then()链式写法,代码更简洁
  3. 内存安全:回调执行后自动删除缓存,避免内存泄漏
  4. 可扩展性:轻松添加其他原生功能的调用逻辑,只需在Flutter端扩展业务判断即可

内容的提问来源于stack exchange,提问作者sanil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 21:06:32