diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerConstantsCache.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerConstantsCache.java index 074d57e806ae..827fa04e203a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerConstantsCache.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerConstantsCache.java @@ -27,8 +27,7 @@ * On init(...), a background thread: * 1) calls MMKV.initialize(...) * 2) reads both keys, parses them into Maps - * 3) builds a WritableNativeMap from the full constants map via Arguments.makeNativeMap(...) - * 4) countDown()s loadLatch + * 3) countDown()s loadLatch * * Exposed methods all block until that single background load finishes: * • getCachedConstants() → Map or null @@ -80,8 +79,7 @@ public static UIManagerConstantsCache getInstance() { * constants are accessed. This kicks off: * 1) MMKV.initialize(...) * 2) A background thread that reads two MMKV keys, parses them → Maps, - * then builds a WritableNativeMap from the full constants, and finally - * countDown()s loadLatch. + * and countDown()s loadLatch. */ public synchronized void init(Context appContext) { if (initCalled) { @@ -173,15 +171,6 @@ public synchronized void init(Context appContext) { } Log.v(TAG, "No bubblingEventTypes found in MMKV."); } - - // 2c) Build WritableNativeMap from full constants (if available) - synchronized (this) { - if (cachedConstants != null) { - cachedNativeMap = Arguments.makeNativeMap(cachedConstants); - } else { - cachedNativeMap = null; - } - } } finally { // Signal load completion loadLatch.countDown(); @@ -224,8 +213,14 @@ public Map getCachedBubblingEventsTypes() { } /** - * Blocks until background-load (and WritableNativeMap build) finishes. - * @return pre-built WritableNativeMap or null if no full-constants available. + * Blocks until the background load finishes, then returns the full constants as a + * WritableNativeMap, building it on the first call. + * + * The map is built here rather than on the loading thread because constructing a + * WritableNativeMap loads React Native's native library, which callers of this method + * already require. + * + * @return WritableNativeMap or null if no full-constants available. */ public WritableNativeMap getUIManagerConstantsAsWritableMap() { try { @@ -236,6 +231,9 @@ public WritableNativeMap getUIManagerConstantsAsWritableMap() { return null; } synchronized (this) { + if (cachedNativeMap == null && cachedConstants != null) { + cachedNativeMap = Arguments.makeNativeMap(cachedConstants); + } return cachedNativeMap; } }