From 65d52a59b044b2e8f7712af5542c4649689363fa Mon Sep 17 00:00:00 2001 From: David Vacca Date: Fri, 1 May 2020 00:17:38 -0700 Subject: [PATCH] Set layout metrics during initial render of Fabric Summary: This diff refactors the initial render of Fabric in order to set the layout metrics as we start the surface. This prevents to create an additional fabric commit during initial render. Also this migth help fixing T63495589 (I wasn't able to repro T63495589 again when using this diff) changelog: [Internal][Android] Internal change to reduce the amount of commits during initial render of Fabric Reviewed By: JoshuaGross Differential Revision: D21330072 fbshipit-source-id: 758c49b52ea4c12d5623b7c7d68c7318f4a6cd83 --- .../facebook/react/ReactInstanceManager.java | 32 ++++++++++++------- .../com/facebook/react/bridge/UIManager.java | 10 ++++++ .../react/fabric/FabricUIManager.java | 9 ++++-- .../facebook/react/uimanager/ReactRoot.java | 3 +- .../react/uimanager/UIManagerModule.java | 10 ++++++ 5 files changed, 48 insertions(+), 16 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 12f0c9e3f47..59ccbbedefb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -1150,21 +1150,29 @@ public class ReactInstanceManager { @Nullable Bundle initialProperties = reactRoot.getAppProperties(); - final int rootTag = - uiManager.addRootView( - reactRoot.getRootViewGroup(), - initialProperties == null - ? new WritableNativeMap() - : Arguments.fromBundle(initialProperties), - reactRoot.getInitialUITemplate()); - reactRoot.setRootViewTag(rootTag); + final int rootTag; + if (reactRoot.getUIManagerType() == FABRIC) { - // Fabric requires to call updateRootLayoutSpecs before starting JS Application, - // this ensures the root will hace the correct pointScaleFactor. - uiManager.updateRootLayoutSpecs( - rootTag, reactRoot.getWidthMeasureSpec(), reactRoot.getHeightMeasureSpec()); + rootTag = + uiManager.startSurface( + reactRoot.getRootViewGroup(), + reactRoot.getJSModuleName(), + initialProperties == null + ? new WritableNativeMap() + : Arguments.fromBundle(initialProperties), + reactRoot.getWidthMeasureSpec(), + reactRoot.getHeightMeasureSpec()); + reactRoot.setRootViewTag(rootTag); reactRoot.setShouldLogContentAppeared(true); } else { + rootTag = + uiManager.addRootView( + reactRoot.getRootViewGroup(), + initialProperties == null + ? new WritableNativeMap() + : Arguments.fromBundle(initialProperties), + reactRoot.getInitialUITemplate()); + reactRoot.setRootViewTag(rootTag); reactRoot.runApplication(); } Systrace.beginAsyncSection( diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java index 89ef6a71720..170fc7fcd3f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java @@ -10,6 +10,7 @@ package com.facebook.react.bridge; import static com.facebook.infer.annotation.ThreadConfined.UI; import android.view.View; +import androidx.annotation.AnyThread; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import com.facebook.infer.annotation.ThreadConfined; @@ -22,6 +23,15 @@ public interface UIManager extends JSIModule, PerformanceCounter { int addRootView( final T rootView, WritableMap initialProps, @Nullable String initialUITemplate); + /** Registers a new root view with width and height. */ + @AnyThread + int startSurface( + final T rootView, + final String moduleName, + final WritableMap initialProps, + int widthMeasureSpec, + int heightMeasureSpec); + /** * Updates the layout specs of the RootShadowNode based on the Measure specs received by * parameters. 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 f16b08a4179..e5239c8db98 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -17,6 +17,7 @@ import static com.facebook.react.fabric.mounting.LayoutMetricsConversions.getYog import static com.facebook.react.uimanager.common.UIManagerType.FABRIC; import android.annotation.SuppressLint; +import android.content.Context; import android.os.SystemClock; import android.view.View; import androidx.annotation.AnyThread; @@ -195,6 +196,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { return rootTag; } + @Override @AnyThread @ThreadConfined(ANY) public int startSurface( @@ -204,8 +206,9 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { int widthMeasureSpec, int heightMeasureSpec) { final int rootTag = ReactRootViewTagGenerator.getNextRootViewTag(); + Context context = rootView.getContext(); ThemedReactContext reactContext = - new ThemedReactContext(mReactApplicationContext, rootView.getContext(), moduleName); + new ThemedReactContext(mReactApplicationContext, context, moduleName); if (ENABLE_FABRIC_LOGS) { FLog.d(TAG, "Starting surface for module: %s and reactTag: %d", moduleName, rootTag); } @@ -219,8 +222,8 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { getMaxSize(widthMeasureSpec), getMinSize(heightMeasureSpec), getMaxSize(heightMeasureSpec), - I18nUtil.getInstance().isRTL(rootView.getContext()), - I18nUtil.getInstance().doLeftAndRightSwapInRTL(rootView.getContext())); + I18nUtil.getInstance().isRTL(context), + I18nUtil.getInstance().doLeftAndRightSwapInRTL(context)); return rootTag; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java index a97220763e4..2fba8c52164 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java @@ -41,9 +41,10 @@ public interface ReactRoot { /** Return native view for root */ ViewGroup getRootViewGroup(); - /** @return Cached values for widthMeasureSpec and heightMeasureSpec */ + /** @return Cached values for widthMeasureSpec. */ int getWidthMeasureSpec(); + /** @return Cached values for and heightMeasureSpec. */ int getHeightMeasureSpec(); /** Sets a flag that determines whether to log that content appeared on next view added. */ diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index a6ce7ff7115..d753e252a56 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -425,6 +425,16 @@ public class UIManagerModule extends ReactContextBaseJavaModule return tag; } + @Override + public int startSurface( + final T rootView, + final String moduleName, + final WritableMap initialProps, + int widthMeasureSpec, + int heightMeasureSpec) { + throw new UnsupportedOperationException(); + } + /** Unregisters a new root view. */ @ReactMethod public void removeRootView(int rootViewTag) {