From d15bc8f4592883ffb5661cffc96df4a1bad53f72 Mon Sep 17 00:00:00 2001 From: Lulu Wu Date: Thu, 26 Oct 2023 04:19:47 -0700 Subject: [PATCH] Fall back to eager view manage loading (#41165) Summary: Currently Bridgeless forces lazy view manager loading, each ReactPackage must implement ```ViewManagerOnDemandReactPackage```. This can bring extra hassle for OSS users in migration. This diff add backward compatibility by falling back to eager view manage loading, after detecting any ReactPackage of current application NOT a subclass of ```ViewManagerOnDemandReactPackage```. Changelog: [Android][Changed] - Fall back to eager view manage loading for Bridgeless Reviewed By: cortinico Differential Revision: D50556405 --- .../facebook/react/runtime/ReactInstance.java | 45 +++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java index 1c5fc2a9db1354..4da3827ab8d708 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java @@ -71,6 +71,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nullable; import kotlin.jvm.functions.Function1; @@ -94,6 +95,7 @@ final class ReactInstance { private final TurboModuleManager mTurboModuleManager; private final FabricUIManager mFabricUIManager; private final JavaTimerManager mJavaTimerManager; + private final Map mViewManagers = new ConcurrentHashMap<>(); @DoNotStrip @Nullable private ComponentNameResolverManager mComponentNameResolverManager; @DoNotStrip @Nullable private UIConstantsProviderManager mUIConstantsProviderManager; @@ -497,8 +499,12 @@ public void registerSegment(int segmentId, String path) { } private @Nullable ViewManager createViewManager(String viewManagerName) { + // Return cached view manager if available, no matter it's eagerly or lazily loaded + if (mViewManagers.containsKey(viewManagerName)) { + return mViewManagers.get(viewManagerName); + } + List packages = mReactPackages; if (mDelegate != null) { - List packages = mReactPackages; if (packages != null) { synchronized (packages) { for (ReactPackage reactPackage : packages) { @@ -507,6 +513,7 @@ public void registerSegment(int segmentId, String path) { ((ViewManagerOnDemandReactPackage) reactPackage) .createViewManager(mBridgelessReactContext, viewManagerName); if (viewManager != null) { + mViewManagers.put(viewManagerName, viewManager); return viewManager; } } @@ -515,7 +522,17 @@ public void registerSegment(int segmentId, String path) { } } - return null; + // Once a view manager is not found in all react packages via lazy loading, fall back to default + // implementation: eagerly initialize all view managers + for (ReactPackage reactPackage : packages) { + List viewManagersInPackage = + reactPackage.createViewManagers(mBridgelessReactContext); + for (ViewManager viewManager : viewManagersInPackage) { + mViewManagers.put(viewManager.getName(), viewManager); + } + } + + return mViewManagers.get(viewManagerName); } private @NonNull Collection getViewManagerNames() { @@ -542,8 +559,28 @@ public void registerSegment(int segmentId, String path) { private @NonNull NativeMap getUIManagerConstants() { List viewManagers = new ArrayList(); - for (String viewManagerName : getViewManagerNames()) { - viewManagers.add(createViewManager(viewManagerName)); + boolean canLoadViewManagersLazily = true; + + List packages = mReactPackages; + for (ReactPackage reactPackage : packages) { + if (!(reactPackage instanceof ViewManagerOnDemandReactPackage)) { + canLoadViewManagersLazily = false; + break; + } + } + // 1, Retrive view managers via on demand loading + if (canLoadViewManagersLazily) { + for (String viewManagerName : getViewManagerNames()) { + viewManagers.add(createViewManager(viewManagerName)); + } + } else { + // 2, There are packages that don't implement ViewManagerOnDemandReactPackage so we retrieve + // view managers via eager loading + for (ReactPackage reactPackage : packages) { + List viewManagersInPackage = + reactPackage.createViewManagers(mBridgelessReactContext); + viewManagers.addAll(viewManagersInPackage); + } } Map constants = UIManagerModule.createConstants(viewManagers, new HashMap<>(), new HashMap<>());