FlutterBridge监听修改一对多

This commit is contained in:
zhulixiao
2026-01-27 10:00:40 +08:00
parent d71234da78
commit e54e11fef1

View File

@@ -4,6 +4,7 @@ import 'dart:html' as html;
import 'package:js/js.dart'; import 'package:js/js.dart';
import 'package:web_tools/utils/model/model.dart'; import 'package:web_tools/utils/model/model.dart';
import 'package:flutter/foundation.dart';
// h5交互通知 原生 {type:'enum',data:'所需参数,可无'} // h5交互通知 原生 {type:'enum',data:'所需参数,可无'}
enum ToFlutterAppEnum { enum ToFlutterAppEnum {
@@ -105,18 +106,15 @@ enum WebInteractionType {
taskKeyOtherPage('TaskKeyOtherPage'), // 其他页面 taskKeyOtherPage('TaskKeyOtherPage'), // 其他页面
taskKeyMineBackpack('TaskKeyMineBackpack'), // 我的装扮背包页面(或者是称号) taskKeyMineBackpack('TaskKeyMineBackpack'), // 我的装扮背包页面(或者是称号)
taskKeyMineWallet('TaskKeyMineWallet'), // 我的钱包页面 taskKeyMineWallet('TaskKeyMineWallet'), // 我的钱包页面
unknown('unknown'), unknown('unknown');
;
const WebInteractionType( const WebInteractionType(this.code);
this.code,
);
final String code; //服务端 key final String code; //服务端 key
factory WebInteractionType.fromCode(String? code) => values.firstWhere( factory WebInteractionType.fromCode(String? code) => values.firstWhere(
(element) => element.code == code, (element) => element.code == code,
orElse: () => WebInteractionType.unknown, orElse: () => WebInteractionType.unknown,
); );
} }
// 原生交互通知 h5 {type:'enum',data:'所需参数 '} // 原生交互通知 h5 {type:'enum',data:'所需参数 '}
@@ -146,7 +144,9 @@ class FlutterBridge {
// 取消监听 'translateResult' 类型的消息 // 取消监听 'translateResult' 类型的消息
FlutterBridge.instance.off(FromJsEnum.translateResult.code); FlutterBridge.instance.off(FromJsEnum.translateResult.code);
* */ * */
final _messageListeners = <String, Function(Map<String, dynamic>)>{}; // final _messageListeners = <String, Function(Map<String, dynamic>)>{};
// 1. 修改这里Value 从 Function 变成 List<Function>
final _messageListeners = <String, List<Function(Map<String, dynamic>)>>{};
var textMap = <String, String>{}; //多语言翻译 var textMap = <String, String>{}; //多语言翻译
FlutterBridge._internal() { FlutterBridge._internal() {
@@ -160,8 +160,19 @@ class FlutterBridge {
try { try {
final Map<String, dynamic> data = jsonDecode(event.data); final Map<String, dynamic> data = jsonDecode(event.data);
final String? type = data['type']; final String? type = data['type'];
// 找到监听列表,遍历调用
if (type != null && _messageListeners.containsKey(type)) { if (type != null && _messageListeners.containsKey(type)) {
_messageListeners[type]?.call(data); final listeners = _messageListeners[type];
if (listeners != null && listeners.isNotEmpty) {
// 使用 List.from 浅拷贝一份进行遍历,防止在回调中移除监听导致并发修改异常
for (final callback in List.from(listeners)) {
try {
callback(data); // 这里的 data 是已经解析好的 Map
} catch (e) {
print("Error in listener callback: $e");
}
}
}
} }
print('Invalid message format from Flutter: $type'); print('Invalid message format from Flutter: $type');
} catch (e) { } catch (e) {
@@ -170,8 +181,19 @@ class FlutterBridge {
} else { } else {
try { try {
final String? type = event.data['type']; final String? type = event.data['type'];
// 找到监听列表,遍历调用
if (type != null && _messageListeners.containsKey(type)) { if (type != null && _messageListeners.containsKey(type)) {
_messageListeners[type]?.call(event.data); final listeners = _messageListeners[type];
if (listeners != null && listeners.isNotEmpty) {
// 使用 List.from 浅拷贝一份进行遍历,防止在回调中移除监听导致并发修改异常
for (final callback in List.from(listeners)) {
try {
callback(event.data); // 这里的 data 是已经解析好的 Map
} catch (e) {
print("Error in listener callback: $e");
}
}
}
} }
print('Invalid message format from Flutter: $type'); print('Invalid message format from Flutter: $type');
} catch (e) { } catch (e) {
@@ -181,24 +203,56 @@ class FlutterBridge {
}); });
} }
// 注册监听某个 type 的消息 /// 仅监听一次,触发后自动移除
void on(String type, Function(Map<String, dynamic>) callback) { void once(String type, Function(Map<String, dynamic>) callback) {
if (_messageListeners.containsKey(type)) { // 定义一个引用,用于在回调内部取消自己
print("Listener for '$type' is already registered."); VoidCallback? cancelRef;
return; // 如果已经注册了这个类型的监听器,就不再重复添加
} // 注册监听
_messageListeners[type] = callback; cancelRef = on(type, (data) {
print("Listener for '$type' has been registered."); // 1. 立即移除监听
cancelRef?.call();
// 2. 执行真正的业务回调
callback(data);
});
} }
// 取消监听某个 type 的消息 /// 3. 核心修改on 方法
void off(String type) { /// 返回一个 VoidCallback调用它即可取消本次监听
VoidCallback on(String type, Function(Map<String, dynamic>) callback) {
if (!_messageListeners.containsKey(type)) { if (!_messageListeners.containsKey(type)) {
print("No listener found for '$type'."); _messageListeners[type] = [];
return; // 如果没有找到监听器,直接返回 }
_messageListeners[type]!.add(callback);
print(
"Listener added for '$type'. Total listeners: ${_messageListeners[type]!.length}",
);
// 返回一个闭包,用于精确移除当前的 callback
return () {
if (_messageListeners.containsKey(type)) {
_messageListeners[type]?.remove(callback);
print(
"One listener removed for '$type'. Remaining: ${_messageListeners[type]?.length}",
);
// 如果该类型没有监听者了,可以选择清理 key
if (_messageListeners[type]!.isEmpty) {
_messageListeners.remove(type);
}
}
};
}
/// 4. 兼容旧代码的 off 方法
/// 警告:这会移除该类型下的【所有】监听器
void off(String type) {
if (_messageListeners.containsKey(type)) {
_messageListeners.remove(type);
print("All listeners for '$type' have been removed.");
} }
_messageListeners.remove(type);
print("Listener for '$type' has been removed.");
} }
// 发送消息给 App通过 WebView 调用 JS 方法) // 发送消息给 App通过 WebView 调用 JS 方法)
@@ -238,29 +292,34 @@ class FlutterBridge {
void toRecharge() => sendToFlutter(ToFlutterAppEnum.toRecharge.code, {}); void toRecharge() => sendToFlutter(ToFlutterAppEnum.toRecharge.code, {});
void toRedDiamond() => sendToFlutter(ToFlutterAppEnum.toRedDiamond.code, {}); void toRedDiamond() => sendToFlutter(ToFlutterAppEnum.toRedDiamond.code, {});
void jumpToH5(String path, String title) => sendToFlutter( void jumpToH5(String path, String title) => sendToFlutter(
ToFlutterAppEnum.jumpToH5.code, {'path': path, 'title': title}); ToFlutterAppEnum.jumpToH5.code,
{'path': path, 'title': title},
);
void toHomepage(String userId) => void toHomepage(String userId) =>
sendToFlutter(ToFlutterAppEnum.toHomepage.code, {'userId': userId}); sendToFlutter(ToFlutterAppEnum.toHomepage.code, {'userId': userId});
void toMonthCardPay(String googleProductId, String iosProductId, void toMonthCardPay(
{otherUserId = ''}) => String googleProductId,
sendToFlutter(ToFlutterAppEnum.toMonthCardPay.code, { String iosProductId, {
'googleProductId': googleProductId, otherUserId = '',
'iosProductId': iosProductId, }) => sendToFlutter(ToFlutterAppEnum.toMonthCardPay.code, {
'otherUserId': otherUserId, 'googleProductId': googleProductId,
}); 'iosProductId': iosProductId,
'otherUserId': otherUserId,
});
void checkGameState(String gameCode) => sendToFlutter( void checkGameState(String gameCode) => sendToFlutter(
ToFlutterAppEnum.checkGameState.code, {'gameCode': gameCode}); ToFlutterAppEnum.checkGameState.code,
{'gameCode': gameCode},
);
void share({ void share({
required String activityId, // 活动id required String activityId, // 活动id
required bool needShareReport, // 是否需要上报分享数据 required bool needShareReport, // 是否需要上报分享数据
ShareCardModel? shareCardModel, // 分享上方卡片 数据,参考客户端参数 ShareCardModel? shareCardModel, // 分享上方卡片 数据,参考客户端参数
}) => }) => sendToFlutter(ToFlutterAppEnum.share.code, {
sendToFlutter(ToFlutterAppEnum.share.code, { "activityId": activityId,
"activityId": activityId, "shareReportKey": needShareReport ? "ActivityShared" : "",
"shareReportKey": needShareReport ? "ActivityShared" : "", ...shareCardModel?.toJson() ?? {},
...shareCardModel?.toJson() ?? {}, });
});
//专属见面礼 //专属见面礼
void taskInviteCodeGift() => void taskInviteCodeGift() =>
@@ -268,14 +327,19 @@ class FlutterBridge {
//解析 URL 并跳转 //解析 URL 并跳转
void taskCommandJump({required String scheme, required String activityId}) => void taskCommandJump({required String scheme, required String activityId}) =>
sendToFlutter(ToFlutterAppEnum.showCommandJump.code, sendToFlutter(ToFlutterAppEnum.showCommandJump.code, {
{"scheme": scheme, "activityId": activityId}); "scheme": scheme,
"activityId": activityId,
});
//跳转至网页 //跳转至网页
void taskToWebViewPage( void taskToWebViewPage({
{required String linkUrl, required String activityId}) => required String linkUrl,
sendToFlutter(ToFlutterAppEnum.showToWebViewPage.code, required String activityId,
{"linkUrl": linkUrl, "activityId": activityId}); }) => sendToFlutter(ToFlutterAppEnum.showToWebViewPage.code, {
"linkUrl": linkUrl,
"activityId": activityId,
});
void checkStartBroadcaster() => void checkStartBroadcaster() =>
sendToFlutter(ToFlutterAppEnum.checkStartBroadcaster.code, {}); sendToFlutter(ToFlutterAppEnum.checkStartBroadcaster.code, {});
@@ -296,7 +360,7 @@ class FlutterBridge {
/** 在直播间或聊天室停留观看n分钟 */ /** 在直播间或聊天室停留观看n分钟 */
void shouldWatchDuration() => void shouldWatchDuration() =>
sendToFlutter(ToFlutterAppEnum.shouldWatchDuration.code, {}); sendToFlutter(ToFlutterAppEnum.shouldWatchDuration.code, {});
/** 在直播间或聊天室发送n条公屏消息 */ /** 在直播间或聊天室发送n条公屏消息 */
void shouldSendPublicMessage() => void shouldSendPublicMessage() =>
sendToFlutter(ToFlutterAppEnum.shouldSendPublicMessage.code, {}); sendToFlutter(ToFlutterAppEnum.shouldSendPublicMessage.code, {});
/** 在直播间或聊天室上麦互动n分钟 */ /** 在直播间或聊天室上麦互动n分钟 */
@@ -311,7 +375,7 @@ class FlutterBridge {
/** 分享n次直播间或聊天室至任意平台 */ /** 分享n次直播间或聊天室至任意平台 */
void shouldShareRoom() => void shouldShareRoom() =>
sendToFlutter(ToFlutterAppEnum.shouldShareRoom.code, {}); sendToFlutter(ToFlutterAppEnum.shouldShareRoom.code, {});
/** 佩戴任意装扮 */ /** 佩戴任意装扮 */
void shouldWearDecoration() => void shouldWearDecoration() =>
sendToFlutter(ToFlutterAppEnum.shouldWearDecoration.code, {}); sendToFlutter(ToFlutterAppEnum.shouldWearDecoration.code, {});
/** 前往语音房 */ /** 前往语音房 */