diff --git a/android/electrode-reactnative-bridge/src/androidTest/java/com/walmartlabs/electrode/reactnative/bridge/BridgeHolderTests.java b/android/electrode-reactnative-bridge/src/androidTest/java/com/walmartlabs/electrode/reactnative/bridge/BridgeHolderTests.java new file mode 100644 index 00000000..6e0f9f3e --- /dev/null +++ b/android/electrode-reactnative-bridge/src/androidTest/java/com/walmartlabs/electrode/reactnative/bridge/BridgeHolderTests.java @@ -0,0 +1,117 @@ +package com.walmartlabs.electrode.reactnative.bridge; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.walmartlabs.electrode.reactnative.bridge.helpers.Logger; + +import org.junit.Before; +import org.junit.Test; + +import java.util.UUID; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertNotNull; +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertNull; + +public class BridgeHolderTests extends BaseBridgeTestCase { + + @Before + public void setUp() { + Logger.overrideLogLevel(Logger.LogLevel.DEBUG); + } + + @Test + public void testRequestHandlerQueuing() { + String KEY_HANDLER = "requestHandler"; + + ElectrodeBridgeRequestHandler requestHandler1 = new ElectrodeBridgeRequestHandler() { + @Override + public void onRequest(@Nullable ElectrodeBridgeRequest payload, @NonNull ElectrodeBridgeResponseListener responseListener) { + + } + }; + + UUID requestHandler1Uuid = ElectrodeBridgeHolder.registerRequestHandler(KEY_HANDLER, requestHandler1); + assertEquals(1, ElectrodeBridgeHolder.mQueuedRequestHandlersRegistration.size()); + assertTrue(ElectrodeBridgeHolder.mQueuedRequestHandlersRegistration.containsKey(KEY_HANDLER)); + assertNotNull(ElectrodeBridgeHolder.mQueuedRequestHandlersRegistration.get(KEY_HANDLER)); + assertEquals(requestHandler1, ElectrodeBridgeHolder.mQueuedRequestHandlersRegistration.get(KEY_HANDLER).getRequestHandler()); + + + ElectrodeBridgeRequestHandler requestHandler2 = new ElectrodeBridgeRequestHandler() { + @Override + public void onRequest(@Nullable ElectrodeBridgeRequest payload, @NonNull ElectrodeBridgeResponseListener responseListener) { + + } + }; + + //Add second request handler, this should replace the first one. + UUID requestHandler2Uuid = ElectrodeBridgeHolder.registerRequestHandler(KEY_HANDLER, requestHandler2); + assertEquals(1, ElectrodeBridgeHolder.mQueuedRequestHandlersRegistration.size()); + assertTrue(ElectrodeBridgeHolder.mQueuedRequestHandlersRegistration.containsKey(KEY_HANDLER)); + assertNotNull(ElectrodeBridgeHolder.mQueuedRequestHandlersRegistration.get(KEY_HANDLER)); + assertEquals(requestHandler2, ElectrodeBridgeHolder.mQueuedRequestHandlersRegistration.get(KEY_HANDLER).getRequestHandler()); + + + //Try removing the first request handler which is already replaced by second + assertNull(ElectrodeBridgeHolder.unregisterRequestHandler(requestHandler1Uuid)); + + //Remove the second request handler + assertEquals(requestHandler2, ElectrodeBridgeHolder.unregisterRequestHandler(requestHandler2Uuid)); + assertEquals(0, ElectrodeBridgeHolder.mQueuedRequestHandlersRegistration.size()); + assertFalse(ElectrodeBridgeHolder.mQueuedRequestHandlersRegistration.containsKey(KEY_HANDLER)); + } + + @Test + public void testEventListenerQueuing() { + String KEY_LISTENER = "eventListener"; + ElectrodeBridgeEventListener eventListener1 = new ElectrodeBridgeEventListener() { + @Override + public void onEvent(@Nullable ElectrodeBridgeEvent eventPayload) { + + } + }; + + UUID eventListener1Uuid = ElectrodeBridgeHolder.addEventListener(KEY_LISTENER, eventListener1); + + assertEquals(1, ElectrodeBridgeHolder.mQueuedEventListenersRegistration.size()); + assertTrue(ElectrodeBridgeHolder.mQueuedEventListenersRegistration.containsKey(KEY_LISTENER)); + assertNotNull(ElectrodeBridgeHolder.mQueuedEventListenersRegistration.get(KEY_LISTENER)); + assertEquals(1, ElectrodeBridgeHolder.mQueuedEventListenersRegistration.get(KEY_LISTENER).size()); + assertEquals(eventListener1, ElectrodeBridgeHolder.mQueuedEventListenersRegistration.get(KEY_LISTENER).get(0).getEventListener()); + + + //Add the second listener + ElectrodeBridgeEventListener eventListener2 = new ElectrodeBridgeEventListener() { + @Override + public void onEvent(@Nullable ElectrodeBridgeEvent eventPayload) { + } + }; + + UUID eventListener2Uuid = ElectrodeBridgeHolder.addEventListener(KEY_LISTENER, eventListener2); + assertEquals(1, ElectrodeBridgeHolder.mQueuedEventListenersRegistration.size()); + assertTrue(ElectrodeBridgeHolder.mQueuedEventListenersRegistration.containsKey(KEY_LISTENER)); + assertNotNull(ElectrodeBridgeHolder.mQueuedEventListenersRegistration.get(KEY_LISTENER)); + assertEquals(2, ElectrodeBridgeHolder.mQueuedEventListenersRegistration.get(KEY_LISTENER).size()); + assertEquals(eventListener1, ElectrodeBridgeHolder.mQueuedEventListenersRegistration.get(KEY_LISTENER).get(0).getEventListener()); + assertEquals(eventListener2, ElectrodeBridgeHolder.mQueuedEventListenersRegistration.get(KEY_LISTENER).get(1).getEventListener()); + + //Remove one listener + assertEquals(eventListener2, ElectrodeBridgeHolder.removeEventListener(eventListener2Uuid)); + assertEquals(1, ElectrodeBridgeHolder.mQueuedEventListenersRegistration.size()); + assertTrue(ElectrodeBridgeHolder.mQueuedEventListenersRegistration.containsKey(KEY_LISTENER)); + assertNotNull(ElectrodeBridgeHolder.mQueuedEventListenersRegistration.get(KEY_LISTENER)); + assertEquals(1, ElectrodeBridgeHolder.mQueuedEventListenersRegistration.get(KEY_LISTENER).size()); + assertEquals(eventListener1, ElectrodeBridgeHolder.mQueuedEventListenersRegistration.get(KEY_LISTENER).get(0).getEventListener()); + + //Remove all listeners + assertEquals(eventListener1, ElectrodeBridgeHolder.removeEventListener(eventListener1Uuid)); + assertEquals(0, ElectrodeBridgeHolder.mQueuedEventListenersRegistration.size()); + assertFalse(ElectrodeBridgeHolder.mQueuedEventListenersRegistration.containsKey(KEY_LISTENER)); + assertNull(ElectrodeBridgeHolder.mQueuedEventListenersRegistration.get(KEY_LISTENER)); + } + +} diff --git a/android/electrode-reactnative-bridge/src/main/java/com/walmartlabs/electrode/reactnative/bridge/ElectrodeBridgeHolder.java b/android/electrode-reactnative-bridge/src/main/java/com/walmartlabs/electrode/reactnative/bridge/ElectrodeBridgeHolder.java index a3b40bb8..b9eea532 100644 --- a/android/electrode-reactnative-bridge/src/main/java/com/walmartlabs/electrode/reactnative/bridge/ElectrodeBridgeHolder.java +++ b/android/electrode-reactnative-bridge/src/main/java/com/walmartlabs/electrode/reactnative/bridge/ElectrodeBridgeHolder.java @@ -17,6 +17,7 @@ package com.walmartlabs.electrode.reactnative.bridge; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import com.walmartlabs.electrode.reactnative.bridge.helpers.Logger; @@ -48,10 +49,10 @@ public final class ElectrodeBridgeHolder { // This solution does not really scale in the sense that if the user sends a 1000 requests // upon native app start, it can become problematic. But I don't see why a user would do that // unless it's a bug in its app - private static final HashMap mQueuedRequestHandlersRegistration = new HashMap<>(); - private static final HashMap mQueuedEventListenersRegistration = new HashMap<>(); - private static final HashMap> mQueuedRequests = new HashMap<>(); - private static final List mQueuedEvents = new ArrayList<>(); + static final HashMap mQueuedRequestHandlersRegistration = new HashMap<>(); + static final HashMap> mQueuedEventListenersRegistration = new HashMap<>(); + static final HashMap> mQueuedRequests = new HashMap<>(); + static final List mQueuedEvents = new ArrayList<>(); static { ElectrodeBridgeTransceiver.registerReactNativeReadyListener(new ElectrodeBridgeTransceiver.ReactNativeReadyListener() { @@ -135,7 +136,12 @@ public static UUID addEventListener(@NonNull String name, UUID eventUUID = UUID.randomUUID(); if (!isReactNativeReady) { Logger.d(TAG, "Queuing event handler registration for event(name=%s). Will register once react native initialization is complete.", name); - mQueuedEventListenersRegistration.put(name, new EventListenerPlaceholder(eventUUID, eventListener)); + List placeholderList = mQueuedEventListenersRegistration.get(name); + if (placeholderList == null) { + placeholderList = new ArrayList<>(); + mQueuedEventListenersRegistration.put(name, placeholderList); + } + placeholderList.add(new EventListenerPlaceholder(eventUUID, eventListener)); return eventUUID; } @@ -153,8 +159,32 @@ public static void addConstantsProvider(@NonNull ConstantsProvider constantsProv * @param eventListenerUuid {@link UUID} * @return */ + @Nullable public static ElectrodeBridgeEventListener removeEventListener(@NonNull UUID eventListenerUuid) { - return electrodeNativeBridge.removeEventListener(eventListenerUuid); + if (!isReactNativeReady) { + ElectrodeBridgeEventListener eventListener = null; + synchronized (mQueuedEventListenersRegistration) { + String key = null; + for (Map.Entry> entry : mQueuedEventListenersRegistration.entrySet()) { + List placeholderList = entry.getValue(); + for (EventListenerPlaceholder placeholder : placeholderList) { + if (eventListenerUuid == placeholder.getUUID()) { + key = entry.getKey(); + eventListener = placeholder.getEventListener(); + placeholderList.remove(placeholder); + break; + } + } + if (placeholderList.size() == 0) { + mQueuedEventListenersRegistration.remove(key); + break; + } + } + } + return eventListener; + } else { + return electrodeNativeBridge.removeEventListener(eventListenerUuid); + } } /** @@ -164,7 +194,20 @@ public static ElectrodeBridgeEventListener removeEventList * @return registerRequestHandler unregistered */ public static ElectrodeBridgeRequestHandler unregisterRequestHandler(@NonNull UUID requestHandlerUuid) { - return electrodeNativeBridge.unregisterRequestHandler(requestHandlerUuid); + if (!isReactNativeReady) { + ElectrodeBridgeRequestHandler requestHandler = null; + synchronized (mQueuedRequestHandlersRegistration) { + for (Map.Entry entry : mQueuedRequestHandlersRegistration.entrySet()) { + if (entry.getValue().getUUID() == requestHandlerUuid) { + requestHandler = entry.getValue().getRequestHandler(); + mQueuedRequestHandlersRegistration.remove(entry.getKey()); + } + } + } + return requestHandler; + } else { + return electrodeNativeBridge.unregisterRequestHandler(requestHandlerUuid); + } } private static void registerQueuedRequestHandlers() { @@ -178,11 +221,15 @@ private static void registerQueuedRequestHandlers() { } private static void registerQueuedEventListeners() { - for (Map.Entry entry : mQueuedEventListenersRegistration.entrySet()) { - electrodeNativeBridge.addEventListener( - entry.getKey(), - entry.getValue().getEventListener(), - entry.getValue().getUUID()); + for (Map.Entry> entry : mQueuedEventListenersRegistration.entrySet()) { + List placeholderList = entry.getValue(); + for (EventListenerPlaceholder placeholder : placeholderList) { + electrodeNativeBridge.addEventListener( + entry.getKey(), + placeholder.getEventListener(), + placeholder.getUUID()); + } + } mQueuedEventListenersRegistration.clear(); }