diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 9687065e2..a50a17b2f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -79,7 +79,7 @@ import com.facebook.react.modules.debug.interfaces.DeveloperSettings; import com.facebook.react.modules.fabric.ReactFabric; import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.UIImplementationProvider; -import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.UIManagerHelper; import com.facebook.react.uimanager.ViewManager; import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper; import com.facebook.soloader.SoLoader; @@ -1011,7 +1011,7 @@ public class ReactInstanceManager { CatalystInstance catalystInstance) { Log.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()"); Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "attachRootViewToInstance"); - UIManager uiManagerModule = rootView.isFabric() ? catalystInstance.getJSIModule(UIManager.class) : catalystInstance.getNativeModule(UIManagerModule.class); + UIManager uiManagerModule = UIManagerHelper.getUIManager(mCurrentReactContext, rootView.isFabric()); final int rootTag = uiManagerModule.addRootView(rootView); rootView.setRootViewTag(rootTag); rootView.invokeJSEntryPoint(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java index 6fbe25e82..ddf80d63c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java @@ -44,6 +44,7 @@ import com.facebook.react.uimanager.IllegalViewOperationException; import com.facebook.react.uimanager.JSTouchDispatcher; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.RootView; +import com.facebook.react.uimanager.UIManagerHelper; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.common.MeasureSpecProvider; import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout; @@ -402,10 +403,9 @@ public class ReactRootView extends SizeMonitoringFrameLayout new GuardedRunnable(reactApplicationContext) { @Override public void runGuarded() { - reactApplicationContext - .getCatalystInstance() - .getNativeModule(UIManagerModule.class) - .updateRootLayoutSpecs(getRootViewTag(), widthMeasureSpec, heightMeasureSpec); + UIManagerHelper + .getUIManager(reactApplicationContext, isFabric()) + .updateRootLayoutSpecs(getRootViewTag(), widthMeasureSpec, heightMeasureSpec); } }); } 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 6cbca5de6..924f84189 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java @@ -3,6 +3,8 @@ package com.facebook.react.bridge; import com.facebook.react.uimanager.common.MeasureSpecProvider; import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout; +import javax.annotation.Nullable; + public interface UIManager extends JSIModule { /** @@ -10,4 +12,19 @@ public interface UIManager extends JSIModule { */ int addRootView(final T rootView); + /** + * Updates the layout specs of the RootShadowNode based on the Measure specs received by + * parameters. + */ + void updateRootLayoutSpecs(int rootTag, int widthMeasureSpec, int heightMeasureSpec); + + /** + * Dispatches the commandId received by parameter to the view associated with the reactTag. + * The command will be processed in the UIThread. + * + * @param reactTag {@link int} that identifies the view that will receive this command + * @param commandId {@link int} command id + * @param commandArgs {@link ReadableArray} parameters associated with the command + */ + void dispatchViewManagerCommand(int reactTag, int commandId, @Nullable ReadableArray commandArgs); } 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 ce8046092..31a2a866f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -16,6 +16,7 @@ import android.view.View; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.GuardedRunnable; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableNativeMap; import com.facebook.react.bridge.UIManager; @@ -35,8 +36,10 @@ import com.facebook.react.uimanager.ViewManagerRegistry; import com.facebook.react.uimanager.common.MeasureSpecProvider; import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout; import java.util.ArrayList; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Set; import javax.annotation.Nullable; /** @@ -280,6 +283,11 @@ public class FabricUIManager implements UIManager { } } + @Deprecated + public void dispatchViewManagerCommand(int reactTag, int commandId, @Nullable ReadableArray commandArgs) { + mUIViewOperationQueue.enqueueDispatchCommand(reactTag, commandId, commandArgs); + } + private void notifyOnBeforeLayoutRecursive(ReactShadowNode node) { if (!node.hasUpdates()) { return; @@ -367,6 +375,16 @@ public class FabricUIManager implements UIManager { return rootTag; } + @Override + public void updateRootLayoutSpecs(int rootViewTag, int widthMeasureSpec, int heightMeasureSpec) { + ReactShadowNode rootNode = mRootShadowNodeRegistry.getNode(rootViewTag); + if (rootNode == null) { + Log.w(ReactConstants.TAG, "Tried to update non-existent root tag: " + rootViewTag); + return; + } + updateRootView(rootNode, widthMeasureSpec, heightMeasureSpec); + } + /** * Updates the root view size and re-render the RN surface. * diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java index 5f124ab88..c1adee2e6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java @@ -788,7 +788,7 @@ public class UIImplementation { mOperationsQueue.enqueueClearJSResponder(); } - public void dispatchViewManagerCommand(int reactTag, int commandId, ReadableArray commandArgs) { + public void dispatchViewManagerCommand(int reactTag, int commandId, @Nullable ReadableArray commandArgs) { assertViewExists(reactTag, "dispatchViewManagerCommand"); mOperationsQueue.enqueueDispatchCommand(reactTag, commandId, commandArgs); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java new file mode 100644 index 000000000..1cf7c6fb3 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java @@ -0,0 +1,32 @@ +package com.facebook.react.uimanager; + +import static com.facebook.react.uimanager.common.ViewType.FABRIC; +import static com.facebook.react.uimanager.common.ViewUtil.getViewType; + +import com.facebook.react.bridge.CatalystInstance; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.UIManager; + +/** + * Helper class for {@link UIManager}. + */ +public class UIManagerHelper { + + /** + * @return a {@link UIManager} that can handle the react tag received by parameter. + */ + public static UIManager getUIManager(ReactContext context, int reactTag) { + return getUIManager(context, getViewType(reactTag) == FABRIC); + } + + /** + * @return a {@link UIManager} that can handle the react tag received by parameter. + */ + public static UIManager getUIManager(ReactContext context, boolean isFabric) { + CatalystInstance catalystInstance = context.getCatalystInstance(); + return isFabric ? + catalystInstance.getJSIModule(UIManager.class) : + catalystInstance.getNativeModule(UIManagerModule.class); + } + +} 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 3ef612874..630f1d973 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -10,6 +10,9 @@ package com.facebook.react.uimanager; import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_CONSTANTS_END; import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_CONSTANTS_START; +import static com.facebook.react.uimanager.common.ViewType.FABRIC; +import static com.facebook.react.uimanager.common.ViewType.PAPER; + import android.content.ComponentCallbacks2; import android.content.res.Configuration; import android.content.Context; @@ -37,6 +40,7 @@ import com.facebook.react.common.ReactConstants; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.common.MeasureSpecProvider; import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout; +import com.facebook.react.uimanager.common.ViewUtil; import com.facebook.react.uimanager.debug.NotThreadSafeViewHierarchyUpdateDebugListener; import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.systrace.Systrace; @@ -582,9 +586,17 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements mUIImplementation.clearJSResponder(); } + @Override @ReactMethod - public void dispatchViewManagerCommand(int reactTag, int commandId, ReadableArray commandArgs) { - mUIImplementation.dispatchViewManagerCommand(reactTag, commandId, commandArgs); + public void dispatchViewManagerCommand(int reactTag, int commandId, @Nullable ReadableArray commandArgs) { + //TODO: this is a temporary approach to support ViewManagerCommands in Fabric until + // the dispatchViewManagerCommand() method is supported by Fabric JS API. + if (ViewUtil.getViewType(reactTag) == FABRIC) { + UIManagerHelper.getUIManager(getReactApplicationContext(), true) + .dispatchViewManagerCommand(reactTag, commandId, commandArgs); + } else { + mUIImplementation.dispatchViewManagerCommand(reactTag, commandId, commandArgs); + } } @ReactMethod diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java index 832b94ce2..183fcf436 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java @@ -647,7 +647,7 @@ public class UIViewOperationQueue { public void enqueueDispatchCommand( int reactTag, int commandId, - ReadableArray commandArgs) { + @Nullable ReadableArray commandArgs) { mOperations.add(new DispatchCommandOperation(reactTag, commandId, commandArgs)); }