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<>());