Line data Source code
1 : import 'dart:async'; 2 : 3 : import 'package:combine/src/id_generator.dart/id_generator.dart'; 4 : import 'package:combine/src/isolate_events.dart'; 5 : import 'package:combine/src/isolate_messenger/internal_isolate_messenger/internal_isolate_messenger.dart'; 6 : import 'package:flutter/services.dart'; 7 : 8 : /// This class receives messages from [MethodChannel.setMessageHandler] 9 : /// registered in [MethodChannelSetup] and sends messages received from Isolate. 10 : class UIMethodChannelMiddleware { 11 : /// Creates new middleware and sets [instance]. 12 2 : UIMethodChannelMiddleware( 13 : this._binaryMessenger, 14 : this._isolateMessenger, 15 2 : ) : _idGenerator = IdGenerator(), 16 : _methodChannels = {}; 17 : 18 : static UIMethodChannelMiddleware? instance; 19 : 20 : final BinaryMessenger _binaryMessenger; 21 : final Set<String> _methodChannels; 22 : final IdGenerator _idGenerator; 23 : final InternalIsolateMessenger _isolateMessenger; 24 : final _messageHandlersCompleter = <int, Completer<ByteData>>{}; 25 : StreamSubscription<IsolateEvent>? _methodChannelEventsSubscription; 26 : 27 : /// Starts listening for [IsolateEvent]s from Isolate and sets middleware for [MethodChannel]. 28 2 : void initialize() { 29 : instance = this; 30 2 : _bindPlatformMessageHandlers(); 31 6 : _methodChannelEventsSubscription = _isolateMessenger.messagesStream 32 6 : .where((event) => event is IsolateEvent) 33 2 : .cast<IsolateEvent>() 34 4 : .listen(_listenForMethodChannelEvents); 35 : } 36 : 37 : /// Free all resources and remove middleware from [MethodChannel]. 38 2 : Future<void> dispose() async { 39 4 : await _methodChannelEventsSubscription?.cancel(); 40 2 : _unbindPlatformMessageHandlers(); 41 : } 42 : 43 1 : void _listenForMethodChannelEvents(IsolateEvent event) { 44 1 : switch (event.runtimeType) { 45 1 : case InvokePlatformChannelEvent: 46 : final invokeEvent = event as InvokePlatformChannelEvent; 47 4 : _send(invokeEvent.channel, invokeEvent.data, invokeEvent.id); 48 : break; 49 1 : case MethodChannelResponseEvent: 50 : final responseEvent = event as MethodChannelResponseEvent; 51 3 : _methodChannelResponse(responseEvent.id, responseEvent.data); 52 : break; 53 : } 54 : } 55 : 56 : /// Send response from IsolateBloc's MessageChannel to the main 57 : /// Isolate's platform channel. 58 1 : void _methodChannelResponse(int id, ByteData? response) { 59 2 : final completer = _messageHandlersCompleter.remove(id); 60 : assert( 61 1 : completer != null, 62 : "Failed to send response from Isolate MessageChannel " 63 : "to the main Isolate's platform channel.\n", 64 : ); 65 1 : completer?.complete(response); 66 : } 67 : 68 : /// Send event to the platform and send response to the IsolateBloc's Isolate. 69 1 : Future<void> _send(String channel, ByteData? message, int id) async { 70 2 : if (!_methodChannels.contains(channel)) { 71 1 : _addPlatformMessageHandler(channel); 72 : } 73 : 74 2 : final response = await _binaryMessenger.send(channel, message); 75 3 : _isolateMessenger.send(PlatformChannelResponseEvent(response, id)); 76 : } 77 : 78 2 : void _bindPlatformMessageHandlers() { 79 6 : _methodChannels.forEach(_bindPlatformMessageHandler); 80 : } 81 : 82 1 : void _addPlatformMessageHandler(String channel) { 83 2 : _methodChannels.add(channel); 84 1 : _bindPlatformMessageHandler(channel); 85 : } 86 : 87 1 : void _bindPlatformMessageHandler(String channel) { 88 3 : _binaryMessenger.setMessageHandler(channel, (message) { 89 1 : final completer = Completer<ByteData>(); 90 2 : final id = _idGenerator(); 91 2 : _messageHandlersCompleter[id] = completer; 92 3 : _isolateMessenger.send(InvokeMethodChannelEvent(message, channel, id)); 93 : 94 1 : return completer.future; 95 : }); 96 : } 97 : 98 2 : void _unbindPlatformMessageHandlers() { 99 3 : for (final channel in _methodChannels) { 100 2 : _binaryMessenger.setMessageHandler(channel, null); 101 : } 102 : } 103 : }