FlutterBridge监听修改一对多
This commit is contained in:
@@ -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,12 +106,9 @@ 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(
|
||||||
@@ -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);
|
_messageListeners.remove(type);
|
||||||
print("Listener for '$type' has been removed.");
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 4. 兼容旧代码的 off 方法
|
||||||
|
/// 警告:这会移除该类型下的【所有】监听器
|
||||||
|
void off(String type) {
|
||||||
|
if (_messageListeners.containsKey(type)) {
|
||||||
|
_messageListeners.remove(type);
|
||||||
|
print("All listeners for '$type' have been removed.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送消息给 App(通过 WebView 调用 JS 方法)
|
// 发送消息给 App(通过 WebView 调用 JS 方法)
|
||||||
@@ -238,25 +292,30 @@ 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, {
|
||||||
|
otherUserId = '',
|
||||||
|
}) => sendToFlutter(ToFlutterAppEnum.toMonthCardPay.code, {
|
||||||
'googleProductId': googleProductId,
|
'googleProductId': googleProductId,
|
||||||
'iosProductId': iosProductId,
|
'iosProductId': iosProductId,
|
||||||
'otherUserId': otherUserId,
|
'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() ?? {},
|
||||||
@@ -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, {});
|
||||||
|
|||||||
Reference in New Issue
Block a user