140 lines
3.6 KiB
Dart
140 lines
3.6 KiB
Dart
// js_bridge.dart
|
|
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'package:webview_flutter/webview_flutter.dart';
|
|
|
|
typedef JSBridgeHandler = Future<dynamic> Function(dynamic data);
|
|
|
|
class ATJSBridge {
|
|
final Map<String, JSBridgeHandler> _handlers = {};
|
|
late WebViewController _controller;
|
|
final Map<String, Completer<dynamic>> _pendingCalls = {};
|
|
int _callId = 0;
|
|
|
|
// 初始化桥梁
|
|
void initialize(WebViewController controller) {
|
|
_controller = controller;
|
|
}
|
|
|
|
// 注册处理方法
|
|
void registerHandler(String name, JSBridgeHandler handler) {
|
|
_handlers[name] = handler;
|
|
}
|
|
|
|
// 移除处理方法
|
|
void removeHandler(String name) {
|
|
_handlers.remove(name);
|
|
}
|
|
|
|
// 调用JS方法
|
|
// 调用JS方法
|
|
Future<dynamic> callHandler(String handlerName, dynamic data) async {
|
|
final callId = 'flutter_${_callId++}_${DateTime.now().millisecondsSinceEpoch}';
|
|
final completer = Completer<dynamic>();
|
|
_pendingCalls[callId] = completer;
|
|
|
|
final message = {
|
|
'type': 'call',
|
|
'handlerName': handlerName,
|
|
'data': data,
|
|
'callId': callId,
|
|
};
|
|
|
|
try {
|
|
await _controller.runJavaScript('''
|
|
if (window.__flutterBridge && typeof window.__flutterBridge.receiveMessage === 'function') {
|
|
window.__flutterBridge.receiveMessage(${jsonEncode(message)});
|
|
} else if (window.JSBridge) {
|
|
window.JSBridge.postMessage(${jsonEncode(message)});
|
|
} else {
|
|
console.error('Flutter bridge not initialized');
|
|
}
|
|
''');
|
|
} catch (e) {
|
|
_pendingCalls.remove(callId);
|
|
completer.completeError(e);
|
|
}
|
|
|
|
// 设置超时
|
|
return completer.future.timeout(const Duration(seconds: 10), onTimeout: () {
|
|
_pendingCalls.remove(callId);
|
|
throw TimeoutException('JS call timeout');
|
|
});
|
|
}
|
|
|
|
// 处理来自JS的消息
|
|
Future<void> handleMessage(String message) async {
|
|
try {
|
|
final Map<String, dynamic> data = jsonDecode(message);
|
|
final type = data['type'] as String?;
|
|
|
|
switch (type) {
|
|
case 'call':
|
|
await _handleJSCall(data);
|
|
break;
|
|
case 'response':
|
|
await _handleJSResponse(data);
|
|
break;
|
|
default:
|
|
print('Unknown message type: $type');
|
|
}
|
|
} catch (e) {
|
|
print('Error handling message: $e');
|
|
}
|
|
}
|
|
|
|
// 处理JS调用的方法
|
|
Future<void> _handleJSCall(Map<String, dynamic> data) async {
|
|
final handlerName = data['handlerName'] as String?;
|
|
final callId = data['callId'] as String?;
|
|
final messageData = data['data'];
|
|
|
|
if (handlerName == null || callId == null) return;
|
|
|
|
dynamic result;
|
|
String? error;
|
|
|
|
try {
|
|
final handler = _handlers[handlerName];
|
|
if (handler != null) {
|
|
result = await handler(messageData);
|
|
} else {
|
|
error = 'Handler "$handlerName" not found';
|
|
}
|
|
} catch (e) {
|
|
error = e.toString();
|
|
}
|
|
|
|
// 发送响应回JS
|
|
final response = {
|
|
'type': 'response',
|
|
'callId': callId,
|
|
'data': result,
|
|
'error': error,
|
|
};
|
|
|
|
await _controller.runJavaScript('''
|
|
if (window.__flutterBridge && window.__flutterBridge.receiveResponse) {
|
|
window.__flutterBridge.receiveResponse(${jsonEncode(response)});
|
|
}
|
|
''');
|
|
}
|
|
|
|
// 处理JS的响应
|
|
Future<void> _handleJSResponse(Map<String, dynamic> data) async {
|
|
final callId = data['callId'] as String?;
|
|
if (callId == null) return;
|
|
|
|
final completer = _pendingCalls[callId];
|
|
if (completer == null) return;
|
|
|
|
if (data['error'] != null) {
|
|
completer.completeError(Exception(data['error']));
|
|
} else {
|
|
completer.complete(data['data']);
|
|
}
|
|
|
|
_pendingCalls.remove(callId);
|
|
}
|
|
}
|