From f58c496e07845e5fb765f051246160077fcf98e4 Mon Sep 17 00:00:00 2001 From: Andrei Shikov Date: Tue, 26 Oct 2021 05:58:58 -0700 Subject: [PATCH] Use context from entry point for prerendering Summary: Some of the prerendered surfaces rely on Android context being present to have correct theming (e.g. for platform colors) and measurements of platform components. This change uses context provided to initialize the surface as themed context before view is attached. This way it is possible to configure theming with `ContextThemeWrapper` the same way as Litho does it for prerendering. The assumption is that any kind of customization done through Android theme will be applied from prerendering entry point as well. Changelog: [Internal] - Use context from surface for prerendering Reviewed By: mdvacca Differential Revision: D31906091 fbshipit-source-id: 344fc96eb2f85ba5b762bee64d1a29443b3fd1d3 --- .../react/fabric/FabricUIManager.java | 20 +++++++--------- .../fabric/mounting/MountingManager.java | 23 +++++++++---------- .../mounting/SurfaceMountingManager.java | 4 +++- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index a1612703952..290c3b6048b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -213,7 +213,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { ThemedReactContext reactContext = new ThemedReactContext( mReactApplicationContext, rootView.getContext(), reactRootView.getSurfaceID(), rootTag); - mMountingManager.startSurface(rootTag, rootView, reactContext); + mMountingManager.startSurface(rootTag, reactContext, rootView); String moduleName = reactRootView.getJSModuleName(); if (ENABLE_FABRIC_LOGS) { FLog.d(TAG, "Starting surface for module: %s and reactTag: %d", moduleName, rootTag); @@ -271,7 +271,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { if (ENABLE_FABRIC_LOGS) { FLog.d(TAG, "Starting surface for module: %s and reactTag: %d", moduleName, rootTag); } - mMountingManager.startSurface(rootTag, rootView, reactContext); + mMountingManager.startSurface(rootTag, reactContext, rootView); // If startSurface is executed in the UIThread then, it uses the ViewportOffset from the View, // Otherwise Fabric relies on calling {@link Binding#setConstraints} method to update the @@ -295,18 +295,14 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { return rootTag; } - public void startSurface(final SurfaceHandler surfaceHandler, final @Nullable View rootView) { + public void startSurface( + final SurfaceHandler surfaceHandler, final Context context, final @Nullable View rootView) { final int rootTag = ReactRootViewTagGenerator.getNextRootViewTag(); - if (rootView == null) { - mMountingManager.startSurface(rootTag); - } else { - Context context = rootView.getContext(); - ThemedReactContext reactContext = - new ThemedReactContext( - mReactApplicationContext, context, surfaceHandler.getModuleName(), rootTag); - mMountingManager.startSurface(rootTag, rootView, reactContext); - } + ThemedReactContext reactContext = + new ThemedReactContext( + mReactApplicationContext, context, surfaceHandler.getModuleName(), rootTag); + mMountingManager.startSurface(rootTag, reactContext, rootView); surfaceHandler.setSurfaceId(rootTag); if (surfaceHandler instanceof SurfaceHandlerBinding) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java index 7e00a20defd..7c303f38c2a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java @@ -75,27 +75,21 @@ public class MountingManager { mMountItemExecutor = mountItemExecutor; } - /** Starts surface and attaches the root view. */ - @AnyThread - public void startSurface( - final int surfaceId, @NonNull final View rootView, ThemedReactContext themedReactContext) { - SurfaceMountingManager mountingManager = startSurface(surfaceId); - mountingManager.attachRootView(rootView, themedReactContext); - } - /** * Starts surface without attaching the view. All view operations executed against that surface * will be queued until the view is attached. */ @AnyThread - public SurfaceMountingManager startSurface(final int surfaceId) { + public SurfaceMountingManager startSurface( + final int surfaceId, ThemedReactContext reactContext, @Nullable View rootView) { SurfaceMountingManager surfaceMountingManager = new SurfaceMountingManager( surfaceId, mJSResponderHandler, mViewManagerRegistry, mRootViewManager, - mMountItemExecutor); + mMountItemExecutor, + reactContext); // There could technically be a race condition here if addRootView is called twice from // different threads, though this is (probably) extremely unlikely, and likely an error. @@ -111,6 +105,11 @@ public class MountingManager { } mMostRecentSurfaceMountingManager = mSurfaceIdToManager.get(surfaceId); + + if (rootView != null) { + surfaceMountingManager.attachRootView(rootView, reactContext); + } + return surfaceMountingManager; } @@ -314,8 +313,8 @@ public class MountingManager { } /** - * Clears the JS Responder specified by {@link #setJSResponder(int, int, int, boolean)}. After - * this method is called, all the touch events are going to be handled by JS. + * Clears the JS Responder specified by {@link SurfaceMountingManager#setJSResponder}. After this + * method is called, all the touch events are going to be handled by JS. */ @UiThread public void clearJSResponder() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java index 737a29559aa..8e1fe87bd7d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java @@ -76,13 +76,15 @@ public class SurfaceMountingManager { @NonNull JSResponderHandler jsResponderHandler, @NonNull ViewManagerRegistry viewManagerRegistry, @NonNull RootViewManager rootViewManager, - @NonNull MountItemExecutor mountItemExecutor) { + @NonNull MountItemExecutor mountItemExecutor, + @NonNull ThemedReactContext reactContext) { mSurfaceId = surfaceId; mJSResponderHandler = jsResponderHandler; mViewManagerRegistry = viewManagerRegistry; mRootViewManager = rootViewManager; mMountItemExecutor = mountItemExecutor; + mThemedReactContext = reactContext; } public boolean isStopped() {