From ce74aa4ed335d4c36ce722d47937b582045e05c4 Mon Sep 17 00:00:00 2001 From: Lulu Wu Date: Tue, 19 Oct 2021 04:09:43 -0700 Subject: [PATCH] Add ReactInstanceEventListener for Venice and expose in FbReactInstanceHolder Summary: Add ```ReactInstanceEventListener``` for Venice and migrate Bridge-only callsites from - FbReactInstanceHolder.getReactInstanceManager().addReactInstanceEventListener() - FbReactInstanceHolder.getReactInstanceManager().removeReactInstanceEventListener() To: - FbReactInstanceHolder.addReactInstanceEventListener() - FbReactInstanceHolder.removeReactInstanceEventListener() Changelog: [Android][Changed] - Add ReactInstanceEventListenerV2 for migration Reviewed By: RSNara Differential Revision: D31501785 fbshipit-source-id: e1cd03f07e28fbb995ea0a1bb76400089a461879 --- .../testing/rule/ReactNativeTestRule.java | 3 +- .../facebook/react/HeadlessJsTaskService.java | 2 +- .../react/ReactInstanceEventListener.java | 23 +++++++++++ .../facebook/react/ReactInstanceManager.java | 38 +++++++++++-------- .../react/uiapp/ReactNativeFlipper.java | 4 +- .../com/helloworld/ReactNativeFlipper.java | 3 +- 6 files changed, 53 insertions(+), 20 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/ReactInstanceEventListener.java diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/ReactNativeTestRule.java b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/ReactNativeTestRule.java index 8d6252f28b8..9c8cc0f9020 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/ReactNativeTestRule.java +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/ReactNativeTestRule.java @@ -10,6 +10,7 @@ package com.facebook.react.testing.rule; import android.app.Activity; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import androidx.test.rule.ActivityTestRule; +import com.facebook.react.ReactInstanceEventListener; import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactPackage; import com.facebook.react.ReactRootView; @@ -90,7 +91,7 @@ public class ReactNativeTestRule implements TestRule { // This threading garbage will be replaced by Surface final AtomicBoolean isLayoutUpdated = new AtomicBoolean(false); mReactInstanceManager.addReactInstanceEventListener( - new ReactInstanceManager.ReactInstanceEventListener() { + new ReactInstanceEventListener() { @Override public void onReactContextInitialized(ReactContext reactContext) { final UIManagerModule uiManagerModule = diff --git a/ReactAndroid/src/main/java/com/facebook/react/HeadlessJsTaskService.java b/ReactAndroid/src/main/java/com/facebook/react/HeadlessJsTaskService.java index 10d9328150a..d9281268839 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/HeadlessJsTaskService.java +++ b/ReactAndroid/src/main/java/com/facebook/react/HeadlessJsTaskService.java @@ -99,7 +99,7 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); if (reactContext == null) { reactInstanceManager.addReactInstanceEventListener( - new ReactInstanceManager.ReactInstanceEventListener() { + new ReactInstanceEventListener() { @Override public void onReactContextInitialized(ReactContext reactContext) { invokeStartTask(reactContext, taskConfig); diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceEventListener.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceEventListener.java new file mode 100644 index 00000000000..4ea99c508d9 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceEventListener.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react; + +import com.facebook.react.bridge.ReactContext; + +/** + * New Listener interface for react instance events. {@Link + * ReactInstanceManager.ReactInstanceEventListener will be deprecated.} + */ +public interface ReactInstanceEventListener { + + /** + * Called when the react context is initialized (all modules registered). Always called on the UI + * thread. + */ + void onReactContextInitialized(ReactContext context); +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 63b237f25f5..c80602f6dea 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -138,15 +138,17 @@ import java.util.Set; public class ReactInstanceManager { private static final String TAG = ReactInstanceManager.class.getSimpleName(); - /** Listener interface for react instance events. */ - public interface ReactInstanceEventListener { - /** - * Called when the react context is initialized (all modules registered). Always called on the - * UI thread. - */ - void onReactContextInitialized(ReactContext context); - } + /** + * Listener interface for react instance events. This class extends {@Link + * com.facebook.react.ReactInstanceEventListener} as a mitigation for both bridgeless and OSS + * compatibility: We create a separate ReactInstanceEventListener class to remove dependency on + * ReactInstanceManager which is a bridge-specific class, but in the mean time we have to keep + * ReactInstanceManager.ReactInstanceEventListener so OSS won't break. + */ + @Deprecated + public interface ReactInstanceEventListener + extends com.facebook.react.ReactInstanceEventListener {} private final Set mAttachedReactRoots = Collections.synchronizedSet(new HashSet()); @@ -173,8 +175,10 @@ public class ReactInstanceManager { private final Context mApplicationContext; private @Nullable @ThreadConfined(UI) DefaultHardwareBackBtnHandler mDefaultBackButtonImpl; private @Nullable Activity mCurrentActivity; - private final Collection mReactInstanceEventListeners = - Collections.synchronizedList(new ArrayList()); + private final Collection + mReactInstanceEventListeners = + Collections.synchronizedList( + new ArrayList()); // Identifies whether the instance manager is or soon will be initialized (on background thread) private volatile boolean mHasStartedCreatingInitialContext = false; // Identifies whether the instance manager destroy function is in process, @@ -1001,12 +1005,14 @@ public class ReactInstanceManager { } /** Add a listener to be notified of react instance events. */ - public void addReactInstanceEventListener(ReactInstanceEventListener listener) { + public void addReactInstanceEventListener( + com.facebook.react.ReactInstanceEventListener listener) { mReactInstanceEventListeners.add(listener); } /** Remove a listener previously added with {@link #addReactInstanceEventListener}. */ - public void removeReactInstanceEventListener(ReactInstanceEventListener listener) { + public void removeReactInstanceEventListener( + com.facebook.react.ReactInstanceEventListener listener) { mReactInstanceEventListeners.remove(listener); } @@ -1177,16 +1183,16 @@ public class ReactInstanceManager { // There is a race condition here - `finalListeners` can contain null entries // See usage below for more details. - ReactInstanceEventListener[] listeners = - new ReactInstanceEventListener[mReactInstanceEventListeners.size()]; - final ReactInstanceEventListener[] finalListeners = + com.facebook.react.ReactInstanceEventListener[] listeners = + new com.facebook.react.ReactInstanceEventListener[mReactInstanceEventListeners.size()]; + final com.facebook.react.ReactInstanceEventListener[] finalListeners = mReactInstanceEventListeners.toArray(listeners); UiThreadUtil.runOnUiThread( new Runnable() { @Override public void run() { - for (ReactInstanceEventListener listener : finalListeners) { + for (com.facebook.react.ReactInstanceEventListener listener : finalListeners) { // Sometimes this listener is null - probably due to race // condition between allocating listeners with a certain // size, and getting a `final` version of the array on diff --git a/packages/rn-tester/android/app/src/debug/java/com/facebook/react/uiapp/ReactNativeFlipper.java b/packages/rn-tester/android/app/src/debug/java/com/facebook/react/uiapp/ReactNativeFlipper.java index 4a9072566f6..2f927231e73 100644 --- a/packages/rn-tester/android/app/src/debug/java/com/facebook/react/uiapp/ReactNativeFlipper.java +++ b/packages/rn-tester/android/app/src/debug/java/com/facebook/react/uiapp/ReactNativeFlipper.java @@ -4,6 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ + package com.facebook.react.uiapp; import android.content.Context; @@ -19,6 +20,7 @@ import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; import com.facebook.flipper.plugins.react.ReactFlipperPlugin; import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; +import com.facebook.react.ReactInstanceEventListener; import com.facebook.react.ReactInstanceManager; import com.facebook.react.bridge.ReactContext; import com.facebook.react.modules.network.NetworkingModule; @@ -51,7 +53,7 @@ public class ReactNativeFlipper { ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); if (reactContext == null) { reactInstanceManager.addReactInstanceEventListener( - new ReactInstanceManager.ReactInstanceEventListener() { + new ReactInstanceEventListener() { @Override public void onReactContextInitialized(ReactContext reactContext) { reactInstanceManager.removeReactInstanceEventListener(this); diff --git a/template/android/app/src/debug/java/com/helloworld/ReactNativeFlipper.java b/template/android/app/src/debug/java/com/helloworld/ReactNativeFlipper.java index 8b7f0913d12..c3310bac32f 100644 --- a/template/android/app/src/debug/java/com/helloworld/ReactNativeFlipper.java +++ b/template/android/app/src/debug/java/com/helloworld/ReactNativeFlipper.java @@ -19,6 +19,7 @@ import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; import com.facebook.flipper.plugins.react.ReactFlipperPlugin; import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; +import com.facebook.react.ReactInstanceEventListener; import com.facebook.react.ReactInstanceManager; import com.facebook.react.bridge.ReactContext; import com.facebook.react.modules.network.NetworkingModule; @@ -51,7 +52,7 @@ public class ReactNativeFlipper { ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); if (reactContext == null) { reactInstanceManager.addReactInstanceEventListener( - new ReactInstanceManager.ReactInstanceEventListener() { + new ReactInstanceEventListener() { @Override public void onReactContextInitialized(ReactContext reactContext) { reactInstanceManager.removeReactInstanceEventListener(this);