typedef EventHandler = void Function(T args); /// The Custom Events Service that can publish data /// from one module/component to another. class MessageService { static final MessageService _singleton = new MessageService._internal(); Map _callbackMaps = Map(); factory MessageService() { return _singleton; } MessageService._internal(); /// Subscribe to an event topic. Events that /// get posted to that topic will trigger /// the provided handler /// * [topic] The topic to subscribe to /// * [handler] The event handler subscribe(String topic, EventHandler? handler) { List>? handlers = _callbackMaps[topic]; if (handler == null) { _callbackMaps.remove(topic); return; } if (handlers == null) { handlers = []; _callbackMaps[topic] = handlers; } handlers.add(handler); } /// Unsubscribe from the given topic. Your handler /// will no longer recieve events published to this /// topic /// * [topic] The topic to unsubscribe from /// * [handler] The event handler unsubscribe(String topic, {EventHandler? handler}) { if (handler == null) { _callbackMaps.remove(topic); return; } final handlers = _callbackMaps[topic]; if (handlers == null) { return; } // We now need to remove specific handler final handlerIndex = handlers.indexOf(handler); if (handlerIndex >= 0) { handlers.removeAt(handlerIndex); if (handlers.length == 0) { _callbackMaps.remove(topic); } } } /// Publish an Event to given topic. /// * [topic] The topic to publish to /// * [arguments] The arguments to pass to /// the handlers. It's better if custom /// Structure is used. publish(String topic, {T? arguments}) { List>? handlers; try { handlers = _callbackMaps[topic]; } catch (_) { throw FormatException( 'Type mismatch between Publisher Arguments and what Subscriber Expects'); } if (handlers == null || handlers.isEmpty) { return; } handlers.forEach((EventHandler handler) { try { if (arguments != null) { handler(arguments); } else { throw 'arguments null'; } } catch (_) { print('Error Occured while executing handler for topic $topic'); print(_); } }); } }