9.7 KiB
9.7 KiB
🔗 Объяснение прямого вызова Dart кода из JavaScript
📋 Новый подход: Прямой вызов Dart функции
🎯 Принцип:
Вместо создания заглушки, мы устанавливаем настоящий Dart обработчик до инициализации JavaScript bridge, обеспечивая его готовность к моменту первого вызова.
📜 JavaScript код (hostBridgeScript):
window.flutterBridge = {
// Send message from Web to Host
sendMessage: function(message) {
console.log('[Flutter Bridge] Отправка сообщения в Flutter Host:', message);
window.flutter_inappwebview.callHandler('flutterBridge', message);
},
// Receive message from Host to Web - ПРЯМОЙ ВЫЗОВ DART
receiveMessage: function(message) {
console.log('[Flutter Bridge] Получение сообщения от Flutter Host:', message);
// Прямой вызов Dart функции
window.dartHandler(message);
}
};
🔄 Порядок инициализации:
1. Установка Dart обработчика (WebBridge._setupDartHandler())
// В web_bridge.dart - ВЫПОЛНЯЕТСЯ ПЕРВЫМ
void _setupDartHandler() {
js.context['dartHandler'] = (String message) {
// Настоящий Dart обработчик
final bridgeMessage = BridgeMessage.fromJson(jsonDecode(message));
_bridgeManager!.handleIncomingMessage(bridgeMessage);
};
}
2. Инициализация BridgeManager (WebBridge._initializeBridgeManager())
// В web_bridge.dart - ВЫПОЛНЯЕТСЯ ВТОРЫМ
_bridgeManager!.initialize(); // WebTransport.initialize() без заглушки
✅ Преимущества нового подхода:
- Нет заглушки - исключены ошибки "Dart обработчик не определен"
- Прямой вызов - JavaScript сразу вызывает настоящий Dart код
- Простота - меньше промежуточных звеньев
- Надежность - нет проблем с timing'ом
🎯 Где устанавливаются настоящие Payload Handlers?
📍 Место установки:
Настоящие payload handlers устанавливаются в Dart коде в методе _registerHandlers() класса WebBridge.
🔧 Процесс установки:
1. Создание BridgeManager
// В web_bridge.dart
_bridgeManager = BridgeManagerFactory.createWebManager(
evaluateJavaScript: (script) { ... },
sendToHost: (jsonString) { ... },
);
2. Регистрация handlers
// В web_bridge.dart -> _registerHandlers()
_bridgeManager!.registerHandler('ping', PingHandler(sendPayload));
_bridgeManager!.registerHandler('ping_response', PingResponseHandler());
_bridgeManager!.registerHandler('user_info_response', UserInfoResponseHandler());
_bridgeManager!.registerHandler('login_response', LoginResponseHandler());
_bridgeManager!.registerHandler('quiz_submission_response', QuizResponseHandler());
3. Настройка callback
// В web_bridge.dart
_bridgeManager!.onPayloadReceived = (payload) {
debugPrint('📥 [WebBridge] Получен payload через callback: ${payload.runtimeType}');
onPayloadReceived?.call(payload);
};
🎯 Где происходит вызов Dart кода из JS (payload handlers)?
📍 Точка входа:
Вызов Dart кода из JavaScript происходит в методе _handleIncomingMessage() класса BridgeManager.
🔄 Полная цепочка вызова:
1. JavaScript → Dart (в web_bridge.dart):
// Настоящий Dart обработчик, установленный в _setupDartHandler()
js.context['dartHandler'] = (String message) {
// 1. Парсим JSON
final json = jsonDecode(message);
// 2. Создаем BridgeMessage
final bridgeMessage = BridgeMessage.fromJson(json);
// 3. Передаем в BridgeManager
_bridgeManager!.handleIncomingMessage(bridgeMessage);
};
2. BridgeManager → Payload Handler (в bridge_manager.dart):
// В BridgeManager._handleIncomingMessage()
void _handleIncomingMessage(BridgeMessage message) {
// 1. Находим handler по типу
final type = message.type;
final handler = _handlers[type]; // ← Здесь происходит поиск зарегистрированного handler
if (handler != null) {
// 2. Десериализуем payload
final payload = PayloadRegistry.deserialize(message);
if (payload != null) {
// 3. Вызываем callback
if (onPayloadReceived != null) {
onPayloadReceived!.call(payload);
}
// 4. ВЫЗЫВАЕМ НАСТОЯЩИЙ PAYLOAD HANDLER ← ЗДЕСЬ!
handler.handle(payload).then((response) {
if (response != null) {
sendPayload(response);
}
});
}
}
}
3. Payload Handler выполняется (в payload_handlers.dart):
// Пример: PingHandler.handle()
class PingHandler implements PayloadHandler {
@override
Future<BridgePayload?> handle(BridgePayload payload) async {
if (payload is PingPayload) {
// ← ЗДЕСЬ ВЫПОЛНЯЕТСЯ БИЗНЕС-ЛОГИКА!
debugPrint('🏓 [PingHandler] Обработка ping: "${payload.message}"');
// Отправляем pong обратно
final pongPayload = payload.toPong();
_sendPayload(pongPayload);
}
return null;
}
}
🔄 Полная цепочка обработки сообщений:
📥 Входящее сообщение (Host → Web):
1. Flutter Host отправляет BridgeMessage
↓
2. JavaScript: window.flutterBridge.receiveMessage(message)
↓
3. JavaScript: window.dartHandler(message) ← ПРЯМОЙ ВЫЗОВ DART
↓
4. Dart: js.context['dartHandler'](message) ← В web_bridge.dart
↓
5. Dart: BridgeMessage.fromJson(jsonDecode(message))
↓
6. Dart: _bridgeManager!.handleIncomingMessage(bridgeMessage) ← В bridge_manager.dart
↓
7. Dart: BridgeManager находит handler по типу payload
↓
8. Dart: handler.handle(payload) ← НАСТОЯЩИЙ PAYLOAD HANDLER! ← В payload_handlers.dart
📤 Исходящее сообщение (Web → Host):
1. Dart: sendPayload(payload)
↓
2. Dart: _bridgeManager!.sendPayload(payload)
↓
3. Dart: BridgeManager создает BridgeMessage
↓
4. Dart: jsonEncode(bridgeMessage.toJson())
↓
5. Dart: sendToHost(jsonString)
↓
6. JavaScript: flutterBridge.callMethod('sendMessage', [jsonString])
↓
7. Flutter Host получает сообщение
🎯 Примеры Payload Handlers:
🏓 PingHandler (обрабатывает входящие ping):
class PingHandler implements PayloadHandler {
final Function(BridgePayload) _sendPayload;
@override
Future<BridgePayload?> handle(BridgePayload payload) async {
if (payload is PingPayload) {
// Получили ping, отправляем pong обратно
final pongPayload = payload.toPong();
_sendPayload(pongPayload);
}
return null;
}
}
👤 UserInfoResponseHandler (обрабатывает ответы с данными пользователя):
class UserInfoResponseHandler implements PayloadHandler {
@override
Future<BridgePayload?> handle(BridgePayload payload) async {
if (payload is UserInfoResponsePayload) {
// Обрабатываем полученные данные пользователя
debugPrint('Данные пользователя: ${payload.userInfo}');
}
return null;
}
}
🔑 Ключевые моменты:
✅ Новый подход:
- Нет заглушки - исключены ошибки "Dart обработчик не определен"
- Прямой вызов - JavaScript сразу вызывает настоящий Dart код
- Правильный порядок - Dart обработчик устанавливается до инициализации bridge
✅ Payload Handlers:
- Устанавливаются в Dart коде
- Обрабатывают типизированные payload'ы
- Содержат бизнес-логику приложения
- Регистрируются в BridgeManager
- Вызываются в
BridgeManager._handleIncomingMessage()
✅ Порядок инициализации:
_setupDartHandler()→ Настоящий Dart обработчик установлен_bridgeManager!.initialize()→ JavaScript bridge готов_registerHandlers()→ Payload handlers зарегистрированы
✅ Точка вызова Payload Handlers:
- Место:
BridgeManager._handleIncomingMessage() - Условие:
handler.handle(payload) - Контекст: После десериализации payload и вызова callback
Итог: Убрана заглушка, теперь JavaScript напрямую вызывает Dart функцию. Dart обработчик устанавливается до инициализации bridge, что исключает ошибки timing'а. Настоящие payload handlers вызываются в BridgeManager._handleIncomingMessage() после обработки входящего сообщения.