Flutter webview_flutter:如何通过JavaScript Channel向JS返回数据?
解决webview_flutter双向通信中JS获取Flutter本地存储值的问题
问题核心在于JavaScriptChannel的postMessage是单向通知机制,无法直接向JS返回值,需要通过Promise+Flutter主动调用JS回调的方式实现数据回传。
步骤1:修改JS注入代码
让getName方法返回Promise,同时给每个请求标记唯一ID,把resolve函数暂存到全局,等待Flutter返回数据:
function myCustomObj() { this.getName = function() { return new Promise((resolve) => { // 生成唯一请求ID,避免多请求冲突 const requestId = 'req_' + Date.now(); // 把resolve函数存到全局 window[requestId] = resolve; // 向Flutter发送带ID的请求消息 jsBridge.postMessage(JSON.stringify({ action: "GET_NAME_FUNCTION", requestId: requestId })); }); }; } window.myCustomObj = new myCustomObj();
步骤2:修改Flutter端JavaScriptChannel回调
解析JS传来的消息,获取本地存储值后,主动调用对应的JS回调函数返回数据:
..addJavaScriptChannel('jsBridge', onMessageReceived: (JavaScriptMessage message) async { // 解析JSON格式的消息 final Map<String, dynamic> data = jsonDecode(message.message); final String action = data['action']; final String requestId = data['requestId']; if (action == "GET_NAME_FUNCTION") { // 替换为你从本地存储获取值的实际逻辑(比如用shared_preferences) String localName = await SharedPreferences.getInstance().then((prefs) => prefs.getString('user_name') ?? ''); // 调用JS的resolve函数回传数据,完成Promise await controller.runJavaScript(""" if (window['$requestId']) { window['$requestId']('$localName'); delete window['$requestId']; // 清理全局变量,避免内存泄漏 } """); } })
步骤3:JS端调用方式
用async/await或者.then()获取返回值:
// 示例调用 async function fetchUserName() { const userName = await window.myCustomObj.getName(); console.log('获取到本地存储的用户名:', userName); } fetchUserName();
补充说明
- 注意处理本地存储获取的异步逻辑,确保拿到值后再调用JS代码。
- 如果有多个不同的请求类型,可以通过
action字段区分,扩展更多通信场景。
内容的提问来源于stack exchange,提问作者user2708880
相关产品推荐
相关产品推荐

