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();
关键优势
- 完全跨平台:适配Android/iOS,无需使用
dart:js_interop或dart:html等Web专属API - Promise风格调用:支持
async/await和.then()链式写法,代码更简洁 - 内存安全:回调执行后自动删除缓存,避免内存泄漏
- 可扩展性:轻松添加其他原生功能的调用逻辑,只需在Flutter端扩展业务判断即可
内容的提问来源于stack exchange,提问作者sanil
相关产品推荐
相关产品推荐

