Created
June 9, 2025 08:42
-
-
Save ArrayIterator/ea8a925f95e322d18d285a6b17f1d4fb to your computer and use it in GitHub Desktop.
Thread Based Asynchronous One-Way Communication pattern fallback
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package my.unit.utils; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.os.Bundle; | |
import android.os.Parcelable; | |
import androidx.annotation.NonNull; | |
import androidx.annotation.Nullable; | |
import java.io.Serializable; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.concurrent.Executor; | |
import java.util.concurrent.Executors; | |
/** | |
* Communicator class provides a decoupled publisher-subscriber communication pattern. | |
* <p> | |
* This singleton class allows components in the application to communicate without | |
* direct dependencies. Components can register as listeners for specific named channels | |
* and receive notifications when events are published to those channels. | |
* <p> | |
* Usage example: | |
* 1. Register a listener: | |
* Communicator.register("myChannel", new Communicator.Listener() {...}); | |
* <p> | |
* 2. Send a notification: | |
* Communicator.notify("myChannel", "eventName", eventData); | |
* <p> | |
* 3. Unregister when done: | |
* Communicator.unregister("myChannel"); | |
* | |
* @noinspection unused | |
*/ | |
final public class Communicator { | |
/** | |
* The tag used for logging. | |
*/ | |
public final static String TAG = "XW_COMMUNICATOR"; | |
/** | |
* Predefined channel constant for activity/fragment creation events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String CREATE = "create"; | |
/** | |
* Predefined channel constant for activity/fragment pause events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String PAUSE = "pause"; | |
/** | |
* Predefined channel constant for activity/fragment resume events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String RESUME = "resume"; | |
/** | |
* Predefined channel constant for activity/fragment destroy events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String DESTROY = "destroy"; | |
/** | |
* Predefined channel constant for activity/fragment start events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String START = "start"; | |
/** | |
* Predefined channel constant for activity/fragment stop events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String STOP = "stop"; | |
/** | |
* Predefined channel constant for activity/fragment restart events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String RESTART = "restart"; | |
/** | |
* Predefined channel constant for activity/fragment destroy events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String FINISH = "finish"; | |
/** | |
* Predefined channel constant for activity/fragment error events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String FAIL = "fail"; | |
/** | |
* Predefined channel constant for activity/fragment cancel events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String CANCEL = "cancel"; | |
/** | |
* Predefined channel constant for activity/fragment success events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String SUCCESS = "success"; | |
/** | |
* Predefined channel constant for activity/fragment crash events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String CRASH = "crash"; | |
/** | |
* Predefined channel constant for activity/fragment page start events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String PAGE_START = "page_start"; | |
/** | |
* Predefined channel constant for activity/fragment page stop events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String PAGE_STOP = "page_stop"; | |
/** | |
* Predefined channel constant for activity/fragment page error events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String PAGE_ERROR = "page_error"; | |
/** | |
* Predefined channel constant for activity/fragment error events. | |
* | |
* @noinspection unused | |
*/ | |
public final static String ERROR = "error"; | |
/** | |
* @param eventName The eventName that was received. | |
* This is used to identify the eventName that triggered the listener. | |
* @noinspection unused | |
*/ | |
public record ListenerValue(@NonNull String eventName, @Nullable Object data) { | |
/** | |
* Constructor for the ListenerValue class. | |
* This constructor initializes the eventName and data fields. | |
* | |
* @param eventName The eventName that was received | |
* @param data The data associated with the eventName (can be null) | |
*/ | |
public ListenerValue { | |
} | |
/** | |
* Checks if the eventName matches the provided event. | |
* | |
* @param event The event to check against | |
* @return true if the eventName matches, false otherwise | |
* @noinspection BooleanMethodIsAlwaysInverted | |
*/ | |
public <T extends String> boolean is(@NonNull T event) { | |
return event.equals(eventName); | |
} | |
/** | |
* Factory method to create a new instance of ListenerValue. | |
* This method is used to create a new instance of the ListenerValue class with the specified eventName and data. | |
* | |
* @param eventName The eventName that was received. | |
* @param data The data associated with the eventName (can be null). | |
* @return A new instance of ListenerValue with the specified eventName and data. | |
*/ | |
public static <T> ListenerValue create(@NonNull String eventName, @Nullable T data) { | |
return new ListenerValue(eventName, data); | |
} | |
/** | |
* Get the data as a String. | |
* | |
* @param defaultValue string default value | |
* @return String data or default value | |
*/ | |
@Nullable | |
public String getString(@Nullable String defaultValue) { | |
if ((data instanceof String)) { | |
return (String) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as a String. | |
* | |
* @return String data or null | |
*/ | |
@Nullable | |
public String getString() { | |
if ((data instanceof String)) { | |
return (String) data; | |
} | |
return null; | |
} | |
/** | |
* Get the data as a Bundle. | |
* | |
* @param defaultValue bundle default value | |
* @return Bundle data or default value | |
*/ | |
@Nullable | |
public Bundle getBundle(@Nullable Bundle defaultValue) { | |
if ((data instanceof Bundle)) { | |
return (Bundle) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as a Bundle. | |
* | |
* @return Bundle data or null | |
*/ | |
@Nullable | |
public Bundle getBundle() { | |
if ((data instanceof Bundle)) { | |
return (Bundle) data; | |
} | |
return null; | |
} | |
/** | |
* Get the data as a Context. | |
* | |
* @param defaultValue context default value | |
* @return Context data or default value | |
*/ | |
@Nullable | |
public Context getContext(@Nullable Context defaultValue) { | |
if ((data instanceof Context)) { | |
return (Context) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as a Context. | |
* | |
* @return Context data or null | |
*/ | |
@Nullable | |
public Context getContext() { | |
if ((data instanceof Context)) { | |
return (Context) data; | |
} | |
return null; | |
} | |
/** | |
* Get the data as an Object. | |
* | |
* @param defaultValue object default value | |
* @return Object data or default value | |
*/ | |
@Nullable | |
public Object getObject(@Nullable Object defaultValue) { | |
if ((data != null)) { | |
return data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as an Object. | |
* | |
* @return Object data or null | |
*/ | |
@Nullable | |
public Object getObject() { | |
return data; | |
} | |
/** | |
* Get the data as a Boolean. | |
* | |
* @param defaultValue boolean default value | |
* @return Boolean data or default value | |
*/ | |
public boolean getBoolean(@NonNull Boolean defaultValue) { | |
if ((data instanceof Boolean)) { | |
return (boolean) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as a Boolean. | |
* | |
* @return Boolean data or null | |
*/ | |
public boolean getBoolean() { | |
if ((data instanceof Boolean)) { | |
return (boolean) data; | |
} | |
return false; | |
} | |
/** | |
* Get the data as an Integer. | |
* | |
* @param defaultValue integer default value | |
* @return Integer data or default value | |
*/ | |
public int getInteger(int defaultValue) { | |
if ((data instanceof Integer)) { | |
return (int) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as an Integer. | |
* | |
* @return Integer data or null | |
*/ | |
@Nullable | |
public Integer getInteger() { | |
if ((data instanceof Integer)) { | |
return (int) data; | |
} | |
return null; | |
} | |
/** | |
* Get the data as a Long. | |
* | |
* @param defaultValue long default value | |
* @return Long data or default value | |
*/ | |
public long getLong(long defaultValue) { | |
if ((data instanceof Long)) { | |
return (long) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as a Long. | |
* | |
* @return Long data or null | |
*/ | |
@Nullable | |
public Long getLong() { | |
if ((data instanceof Long)) { | |
return (Long) data; | |
} | |
return null; | |
} | |
/** | |
* Get the data as a Float. | |
* | |
* @param defaultValue float default value | |
* @return Float data or default value | |
*/ | |
public float getFloat(float defaultValue) { | |
if ((data instanceof Float)) { | |
return (float) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as a Float. | |
* | |
* @return Float data or null | |
*/ | |
@Nullable | |
public Float getFloat() { | |
if ((data instanceof Float)) { | |
return (Float) data; | |
} | |
return null; | |
} | |
/** | |
* Get the data as a Double. | |
* | |
* @param defaultValue double default value | |
* @return Double data or default value | |
*/ | |
public double getDouble(double defaultValue) { | |
if ((data instanceof Double)) { | |
return (double) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as a Double. | |
* | |
* @return Double data or null | |
*/ | |
@Nullable | |
public Double getDouble() { | |
if ((data instanceof Double)) { | |
return (Double) data; | |
} | |
return null; | |
} | |
/** | |
* Get the data as an Intent. | |
* | |
* @param defaultValue intent default value | |
* @return Intent data or default value | |
*/ | |
public Intent getIntent(@Nullable Intent defaultValue) { | |
if ((data instanceof Intent)) { | |
return (Intent) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as an Intent. | |
* | |
* @return Intent data or null | |
*/ | |
@Nullable | |
public Intent getIntent() { | |
if ((data instanceof Intent)) { | |
return (Intent) data; | |
} | |
return null; | |
} | |
/** | |
* Get the data as a Parcelable. | |
* | |
* @param defaultValue parcelable default value | |
* @return Parcelable data or default value | |
*/ | |
public Parcelable getParcelable(@Nullable Parcelable defaultValue) { | |
if ((data instanceof Parcelable)) { | |
return (Parcelable) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as a Parcelable. | |
* | |
* @return Parcelable data or null | |
*/ | |
@Nullable | |
public Parcelable getParcelable() { | |
if ((data instanceof Parcelable)) { | |
return (Parcelable) data; | |
} | |
return null; | |
} | |
/** | |
* Get the data as a Serializable. | |
* | |
* @param defaultValue serializable default value | |
* @return Serializable data or default value | |
*/ | |
public Serializable getSerializable(@Nullable Serializable defaultValue) { | |
if ((data instanceof Serializable)) { | |
return (Serializable) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as a Serializable. | |
* | |
* @return Serializable data or null | |
*/ | |
@Nullable | |
public Serializable getSerializable() { | |
if ((data instanceof Serializable)) { | |
return (Serializable) data; | |
} | |
return null; | |
} | |
// List | |
/** | |
* Get the data as a List. | |
* | |
* @param defaultValue list default value | |
* @return List data or default value | |
*/ | |
public List<?> getList(@Nullable List<?> defaultValue) { | |
if ((data instanceof List)) { | |
return (List<?>) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as a List. | |
* | |
* @return List data or null | |
*/ | |
@Nullable | |
public List<?> getList() { | |
if ((data instanceof List)) { | |
return (List<?>) data; | |
} | |
return null; | |
} | |
// ArrayList | |
/** | |
* Get the data as an ArrayList. | |
* | |
* @param defaultValue arraylist default value | |
* @return ArrayList data or default value | |
*/ | |
public ArrayList<?> getArrayList(@NonNull ArrayList<?> defaultValue) { | |
if ((data instanceof ArrayList)) { | |
return (ArrayList<?>) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as an ArrayList. | |
* | |
* @return ArrayList data or null | |
*/ | |
@Nullable | |
public ArrayList<?> getArrayList() { | |
if ((data instanceof ArrayList)) { | |
return (ArrayList<?>) data; | |
} | |
return null; | |
} | |
// HashMap | |
/** | |
* Get the data as a HashMap. | |
* | |
* @param defaultValue hashmap default value | |
* @return HashMap data or default value | |
*/ | |
public HashMap<?, ?> getHashMap(@NonNull HashMap<?, ?> defaultValue) { | |
if ((data instanceof HashMap)) { | |
return (HashMap<?, ?>) data; | |
} | |
return defaultValue; | |
} | |
/** | |
* Get the data as a HashMap. | |
* | |
* @return HashMap data or null | |
*/ | |
@Nullable | |
public HashMap<?, ?> getHashMap() { | |
if ((data instanceof HashMap)) { | |
return (HashMap<?, ?>) data; | |
} | |
return null; | |
} | |
} | |
/** | |
* Interface for listeners that will receive events from the Communicator. | |
* Classes that want to receive events must implement this interface and | |
* register themselves with the Communicator. | |
*/ | |
public interface Listener { | |
/** | |
* Called when an eventName is received with a generic Object data payload. | |
* This variant is useful for passing structured data between components. | |
* | |
* @param channelName The channelName that was received | |
* @param eventName The eventName that was received | |
* @param data The data associated with the eventName (can be null) | |
*/ | |
void run(@NonNull String channelName, @NonNull String eventName, @NonNull ListenerValue data); | |
} | |
/** | |
* The singleton instance of the Communicator class. | |
*/ | |
private static Communicator sInstance; | |
/** | |
* The executor used for dispatching events asynchronously. | |
* Using a single thread executor ensures that notifications are processed | |
* sequentially, avoiding race conditions. | |
*/ | |
@NonNull | |
private final Executor executor = Executors.newSingleThreadExecutor(); | |
/** | |
* Maps channel names to their registered listeners. | |
* Each channel can have multiple listeners. | |
*/ | |
private Map<String, List<Listener>> mListenersMap; | |
/** | |
* Private constructor to enforce singleton pattern. | |
*/ | |
private Communicator() { | |
// Initialize the listener map lazily when first needed | |
} | |
/** | |
* Returns the singleton instance of the Communicator. | |
* If the instance doesn't exist, it creates a new one. | |
* | |
* @return The singleton instance of the Communicator | |
*/ | |
public static Communicator getInstance() { | |
if (sInstance == null) { | |
sInstance = new Communicator(); | |
} | |
return sInstance; | |
} | |
/** | |
* Adds a listener to a specified channel. | |
* The listener will be notified of all events published to this channel. | |
* | |
* @param channel The channel name to subscribe to | |
* @param listener The listener that will receive events | |
*/ | |
public void addListener(@NonNull String channel, @NonNull Listener listener) { | |
if (mListenersMap == null) { | |
mListenersMap = new HashMap<>(); | |
} | |
// Get or create the listener list for this channel | |
List<Listener> listeners = mListenersMap.computeIfAbsent(channel, k -> new ArrayList<>()); | |
// Add the listener if it's not already in the list | |
if (!listeners.contains(listener)) { | |
listeners.add(listener); | |
} | |
} | |
/** | |
* Removes a specific listener from a specified channel. | |
* | |
* @param channel The channel name to unsubscribe from | |
* @param listener The listener to remove | |
*/ | |
public void removeListener(@NonNull String channel, @NonNull Listener listener) { | |
if (mListenersMap != null) { | |
List<Listener> listeners = mListenersMap.get(channel); | |
if (listeners != null) { | |
listeners.remove(listener); | |
// Clean up empty lists to prevent memory leaks | |
if (listeners.isEmpty()) { | |
mListenersMap.remove(channel); | |
} | |
} | |
} | |
} | |
/** | |
* Removes all listeners from a specified channel. | |
* | |
* @param channel The channel name to clear | |
*/ | |
public void removeListener(@NonNull String channel) { | |
if (mListenersMap != null) { | |
mListenersMap.remove(channel); | |
} | |
} | |
/** | |
* Removes a specific listener from all channels it's registered to. | |
* | |
* @param listener The listener to remove from all channels | |
*/ | |
public void removeListener(@NonNull Listener listener) { | |
if (mListenersMap == null) { | |
return; | |
} | |
// Create a copy of the keys to avoid ConcurrentModificationException | |
List<String> keys = new ArrayList<>(mListenersMap.keySet()); | |
for (String channel : keys) { | |
List<Listener> listeners = mListenersMap.get(channel); | |
if (listeners != null) { | |
listeners.remove(listener); | |
// Clean up empty lists | |
if (listeners.isEmpty()) { | |
mListenersMap.remove(channel); | |
} | |
} | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an eventName with ListenerValue data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param data The data to send with the eventName (can be null) | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull ListenerValue data) { | |
if (mListenersMap != null) { | |
String eventName = data.eventName; | |
List<Listener> listeners = mListenersMap.get(channel); | |
if (listeners == null || listeners.isEmpty()) { | |
return; | |
} | |
// Create a copy to avoid concurrent modification issues | |
final List<Listener> listenersCopy = new ArrayList<>(listeners); | |
for (Listener listener : listenersCopy) { | |
doExecute(listener, channel, eventName, data); | |
} | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an eventName with Object data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The eventName identifier | |
* @param data The data to send with the eventName (can be null) | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull String eventName, @Nullable Object data) { | |
if (mListenersMap != null) { | |
doNotify(channel, ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The event identifier | |
* @param data The bundle data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull String eventName, @NonNull Context data) { | |
if (mListenersMap != null) { | |
doNotify(channel, ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The event identifier | |
* @param data The bundle data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull String eventName, @NonNull String data) { | |
if (mListenersMap != null) { | |
doNotify(channel, ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The event identifier | |
* @param data The integer data to send with the event | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull String eventName, int data) { | |
if (mListenersMap != null) { | |
doNotify(channel, ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The event identifier | |
* @param data The long data to send with the event | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull String eventName, long data) { | |
if (mListenersMap != null) { | |
doNotify(channel, ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The event identifier | |
* @param data The boolean data to send with the event | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull String eventName, boolean data) { | |
if (mListenersMap != null) { | |
doNotify(channel, ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The event identifier | |
* @param data The bundle data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull String eventName, @NonNull Bundle data) { | |
if (mListenersMap != null) { | |
doNotify(channel, ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The event identifier | |
* @param data The intent data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull String eventName, @NonNull Intent data) { | |
if (mListenersMap != null) { | |
doNotify(channel, ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The event identifier | |
* @param data The parcelable data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull String eventName, @NonNull Parcelable data) { | |
if (mListenersMap != null) { | |
doNotify(channel, ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The event identifier | |
* @param data The serializable data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull String eventName, @NonNull Serializable data) { | |
if (mListenersMap != null) { | |
doNotify(channel, ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The event identifier | |
* @param data The list data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull String eventName, @NonNull List<?> data) { | |
if (mListenersMap != null) { | |
doNotify(channel, ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The event identifier | |
* @param data The arraylist data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull String eventName, @NonNull ArrayList<?> data) { | |
if (mListenersMap != null) { | |
doNotify(channel, ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The event identifier | |
* @param data The hashmap data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String channel, @NonNull String eventName, @NonNull HashMap<?, ?> data) { | |
if (mListenersMap != null) { | |
doNotify(channel, ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Executes the listener's run method on a background thread. | |
* This method is used internally to ensure that listener notifications | |
* are processed asynchronously without blocking the main thread. | |
* | |
* @param listener The listener to notify | |
* @param channel The channel name whose listeners will be notified | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
private void doExecute(@NonNull Listener listener, @NonNull String channel, @NonNull String eventName, @NonNull ListenerValue data) { | |
executor.execute(() -> { | |
try { | |
listener.run(channel, eventName, data); | |
} catch (Exception e) { | |
// add log | |
} | |
}); | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param data The listener value data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull ListenerValue data) { | |
if (mListenersMap != null) { | |
String eventName = data.eventName; | |
for (String channel : mListenersMap.keySet()) { | |
List<Listener> listeners = mListenersMap.get(channel); | |
if (listeners == null || listeners.isEmpty()) { | |
continue; // Skip if no listeners are registered for this channel | |
} | |
// Create a copy to avoid concurrent modification issues | |
final List<Listener> listenersCopy = new ArrayList<>(listeners); | |
for (Listener listener : listenersCopy) { | |
doExecute(listener, channel, eventName, data); | |
} | |
} | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param eventName The event identifier | |
* @param data The bundle data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String eventName, @NonNull Bundle data) { | |
if (mListenersMap != null) { | |
doNotify(ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param eventName The event identifier | |
* @param data The string data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String eventName, @NonNull String data) { | |
if (mListenersMap != null) { | |
doNotify(ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param eventName The event identifier | |
* @param data The integer data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String eventName, int data) { | |
if (mListenersMap != null) { | |
doNotify(ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param eventName The event identifier | |
* @param data The long data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String eventName, long data) { | |
if (mListenersMap != null) { | |
doNotify(ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param eventName The event identifier | |
* @param data The boolean data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String eventName, boolean data) { | |
if (mListenersMap != null) { | |
doNotify(ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param eventName The event identifier | |
* @param data The bundle data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String eventName, @NonNull Context data) { | |
if (mListenersMap != null) { | |
doNotify(ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param eventName The event identifier | |
* @param data The intent data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String eventName, @NonNull Intent data) { | |
if (mListenersMap != null) { | |
doNotify(ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param eventName The event identifier | |
* @param data The parcelable data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String eventName, @NonNull Parcelable data) { | |
if (mListenersMap != null) { | |
doNotify(ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param eventName The event identifier | |
* @param data The serializable data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String eventName, @NonNull Serializable data) { | |
if (mListenersMap != null) { | |
doNotify(ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param eventName The event identifier | |
* @param data The list data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String eventName, @NonNull List<?> data) { | |
if (mListenersMap != null) { | |
doNotify(ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param eventName The event identifier | |
* @param data The arraylist data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String eventName, @NonNull ArrayList<?> data) { | |
if (mListenersMap != null) { | |
doNotify(ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param eventName The event identifier | |
* @param data The hashmap data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String eventName, @NonNull HashMap<?, ?> data) { | |
if (mListenersMap != null) { | |
doNotify(ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Notifies all listeners registered to a channel of an event with Bundle data. | |
* The notification is delivered asynchronously on a background thread. | |
* | |
* @param eventName The event identifier | |
* @param data The object data to send with the event (can be null) | |
*/ | |
public void doNotify(@NonNull String eventName, @Nullable Object data) { | |
if (mListenersMap != null) { | |
doNotify(ListenerValue.create(eventName, data)); | |
} | |
} | |
/** | |
* Clears all listeners from all channels. | |
* This should be called when the application is shutting down or when | |
* communication is no longer needed to prevent memory leaks. | |
*/ | |
public void clear() { | |
if (mListenersMap != null) { | |
mListenersMap.clear(); | |
mListenersMap = null; | |
} | |
} | |
/** | |
* Destroys the singleton instance of the Communicator. | |
* This should be called when the application is shutting down or when | |
* communication is no longer needed to prevent memory leaks. | |
*/ | |
public static void destroy() { | |
if (sInstance != null) { | |
sInstance.clear(); | |
sInstance = null; | |
} | |
} | |
/** | |
* Static convenience method to register a listener to the default channel. | |
* Default channel is defined as "XW_COMMUNICATOR". | |
* | |
* @param listener The listener that will receive events | |
*/ | |
public static void attach(@NonNull Listener listener) { | |
register(TAG, listener); | |
} | |
/** | |
* Static convenience method to unregister a listener from the default channel. | |
* Default channel is defined as "XW_COMMUNICATOR". | |
* | |
* @param listener The listener to remove | |
*/ | |
public static void detach(@NonNull Listener listener) { | |
unregister(TAG, listener); | |
} | |
/** | |
* Static convenience method to register a listener to a channel. | |
* | |
* @param channel The channel name to subscribe to | |
* @param listener The listener that will receive events | |
*/ | |
public static void register(@NonNull String channel, @NonNull Listener listener) { | |
getInstance().addListener(channel, listener); | |
} | |
/** | |
* Static convenience method to unregister a listener from a channel. | |
* | |
* @param channel The channel name to unsubscribe from | |
* @param listener The listener to remove | |
*/ | |
public static void unregister(@NonNull String channel, @NonNull Listener listener) { | |
getInstance().removeListener(channel, listener); | |
} | |
/** | |
* Static convenience method to unregister all listeners from a channel. | |
* | |
* @param channel The channel name to clear | |
*/ | |
public static void unregister(@NonNull String channel) { | |
getInstance().removeListener(channel); | |
} | |
/** | |
* Static convenience method to unregister a listener from all channels. | |
* | |
* @param listener The listener to remove from all channels | |
*/ | |
public static void unregister(@NonNull Listener listener) { | |
getInstance().removeListener(listener); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull ListenerValue data) { | |
notify(TAG, data); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull String eventName, @NonNull Object data) { | |
notify(TAG, eventName, data); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull String eventName, int data) { | |
notify(TAG, eventName, data); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull String eventName, long data) { | |
notify(TAG, eventName, data); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull String eventName, boolean data) { | |
notify(TAG, eventName, data); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull String eventName, @NonNull Bundle data) { | |
notify(TAG, eventName, data); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull String eventName, @NonNull String data) { | |
notify(TAG, eventName, data); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull String eventName, @NonNull Context data) { | |
notify(TAG, eventName, data); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull String eventName, @NonNull Intent data) { | |
notify(TAG, eventName, data); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull String eventName, @NonNull Parcelable data) { | |
notify(TAG, eventName, data); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull String eventName, @NonNull Serializable data) { | |
notify(TAG, eventName, data); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull String eventName, @NonNull List<?> data) { | |
notify(TAG, eventName, data); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull String eventName, @NonNull ArrayList<?> data) { | |
notify(TAG, eventName, data); | |
} | |
/** | |
* Static convenience method to notify default listeners of an event with Object data. | |
* | |
* @param eventName The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void send(@NonNull String eventName, @NonNull HashMap<?, ?> data) { | |
notify(TAG, eventName, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull String event, @Nullable Object data) { | |
getInstance().doNotify(channel, event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull String event, int data) { | |
getInstance().doNotify(channel, event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull String event, long data) { | |
getInstance().doNotify(channel, event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull String event, boolean data) { | |
getInstance().doNotify(channel, event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull String event, @NonNull Bundle data) { | |
getInstance().doNotify(channel, event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull String event, @NonNull String data) { | |
getInstance().doNotify(channel, event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull String event, @NonNull Context data) { | |
getInstance().doNotify(channel, event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull String event, @NonNull Intent data) { | |
getInstance().doNotify(channel, event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull String event, @NonNull Parcelable data) { | |
getInstance().doNotify(channel, event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull String event, @NonNull Serializable data) { | |
getInstance().doNotify(channel, event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull String event, @NonNull List<?> data) { | |
getInstance().doNotify(channel, event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull String event, @NonNull ArrayList<?> data) { | |
getInstance().doNotify(channel, event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The channel name whose listeners will be notified | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull String event, @NonNull HashMap<?, ?> data) { | |
getInstance().doNotify(channel, event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param channel The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String channel, @NonNull ListenerValue data) { | |
getInstance().doNotify(channel, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String event, @Nullable Object data) { | |
getInstance().doNotify(event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String event, int data) { | |
getInstance().doNotify(event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String event, long data) { | |
getInstance().doNotify(event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String event, boolean data) { | |
getInstance().doNotify(event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String event, @NonNull Bundle data) { | |
getInstance().doNotify(event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String event, @NonNull String data) { | |
getInstance().doNotify(event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String event, @NonNull Context data) { | |
getInstance().doNotify(event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String event, @NonNull Intent data) { | |
getInstance().doNotify(event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String event, @NonNull Parcelable data) { | |
getInstance().doNotify(event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String event, @NonNull Serializable data) { | |
getInstance().doNotify(event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String event, @NonNull List<?> data) { | |
getInstance().doNotify(event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String event, @NonNull ArrayList<?> data) { | |
getInstance().doNotify(event, data); | |
} | |
/** | |
* Static convenience method to notify listeners of an event with Object data. | |
* | |
* @param event The event identifier | |
* @param data The data to send with the event (can be null) | |
*/ | |
public static void notify(@NonNull String event, @NonNull HashMap<?, ?> data) { | |
getInstance().doNotify(event, data); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment