Add support for View Manager commands in Fabric

Reviewed By: achen1

Differential Revision: D7879104

fbshipit-source-id: fd89acb3941bb03364d18ddedf68a081aef934a0
This commit is contained in:
David Vacca 2018-05-14 09:22:13 -07:00 committed by Facebook Github Bot
parent 398f1d8ddd
commit 3ac914478d
8 changed files with 89 additions and 10 deletions

View File

@ -79,7 +79,7 @@ import com.facebook.react.modules.debug.interfaces.DeveloperSettings;
import com.facebook.react.modules.fabric.ReactFabric; import com.facebook.react.modules.fabric.ReactFabric;
import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.UIImplementationProvider; 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.uimanager.ViewManager;
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper; import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
import com.facebook.soloader.SoLoader; import com.facebook.soloader.SoLoader;
@ -1011,7 +1011,7 @@ public class ReactInstanceManager {
CatalystInstance catalystInstance) { CatalystInstance catalystInstance) {
Log.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()"); Log.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()");
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "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); final int rootTag = uiManagerModule.addRootView(rootView);
rootView.setRootViewTag(rootTag); rootView.setRootViewTag(rootTag);
rootView.invokeJSEntryPoint(); rootView.invokeJSEntryPoint();

View File

@ -44,6 +44,7 @@ import com.facebook.react.uimanager.IllegalViewOperationException;
import com.facebook.react.uimanager.JSTouchDispatcher; import com.facebook.react.uimanager.JSTouchDispatcher;
import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.RootView; import com.facebook.react.uimanager.RootView;
import com.facebook.react.uimanager.UIManagerHelper;
import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.common.MeasureSpecProvider; import com.facebook.react.uimanager.common.MeasureSpecProvider;
import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout; import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout;
@ -402,10 +403,9 @@ public class ReactRootView extends SizeMonitoringFrameLayout
new GuardedRunnable(reactApplicationContext) { new GuardedRunnable(reactApplicationContext) {
@Override @Override
public void runGuarded() { public void runGuarded() {
reactApplicationContext UIManagerHelper
.getCatalystInstance() .getUIManager(reactApplicationContext, isFabric())
.getNativeModule(UIManagerModule.class) .updateRootLayoutSpecs(getRootViewTag(), widthMeasureSpec, heightMeasureSpec);
.updateRootLayoutSpecs(getRootViewTag(), widthMeasureSpec, heightMeasureSpec);
} }
}); });
} }

View File

@ -3,6 +3,8 @@ package com.facebook.react.bridge;
import com.facebook.react.uimanager.common.MeasureSpecProvider; import com.facebook.react.uimanager.common.MeasureSpecProvider;
import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout; import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout;
import javax.annotation.Nullable;
public interface UIManager extends JSIModule { public interface UIManager extends JSIModule {
/** /**
@ -10,4 +12,19 @@ public interface UIManager extends JSIModule {
*/ */
<T extends SizeMonitoringFrameLayout & MeasureSpecProvider> int addRootView(final T rootView); <T extends SizeMonitoringFrameLayout & MeasureSpecProvider> 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);
} }

View File

@ -16,6 +16,7 @@ import android.view.View;
import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.GuardedRunnable; import com.facebook.react.bridge.GuardedRunnable;
import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableNativeMap; import com.facebook.react.bridge.ReadableNativeMap;
import com.facebook.react.bridge.UIManager; 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.MeasureSpecProvider;
import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout; import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set;
import javax.annotation.Nullable; 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) { private void notifyOnBeforeLayoutRecursive(ReactShadowNode node) {
if (!node.hasUpdates()) { if (!node.hasUpdates()) {
return; return;
@ -367,6 +375,16 @@ public class FabricUIManager implements UIManager {
return rootTag; 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. * Updates the root view size and re-render the RN surface.
* *

View File

@ -788,7 +788,7 @@ public class UIImplementation {
mOperationsQueue.enqueueClearJSResponder(); mOperationsQueue.enqueueClearJSResponder();
} }
public void dispatchViewManagerCommand(int reactTag, int commandId, ReadableArray commandArgs) { public void dispatchViewManagerCommand(int reactTag, int commandId, @Nullable ReadableArray commandArgs) {
assertViewExists(reactTag, "dispatchViewManagerCommand"); assertViewExists(reactTag, "dispatchViewManagerCommand");
mOperationsQueue.enqueueDispatchCommand(reactTag, commandId, commandArgs); mOperationsQueue.enqueueDispatchCommand(reactTag, commandId, commandArgs);
} }

View File

@ -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);
}
}

View File

@ -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_END;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_CONSTANTS_START; 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.ComponentCallbacks2;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.Context; 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.module.annotations.ReactModule;
import com.facebook.react.uimanager.common.MeasureSpecProvider; import com.facebook.react.uimanager.common.MeasureSpecProvider;
import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout; 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.debug.NotThreadSafeViewHierarchyUpdateDebugListener;
import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.systrace.Systrace; import com.facebook.systrace.Systrace;
@ -582,9 +586,17 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
mUIImplementation.clearJSResponder(); mUIImplementation.clearJSResponder();
} }
@Override
@ReactMethod @ReactMethod
public void dispatchViewManagerCommand(int reactTag, int commandId, ReadableArray commandArgs) { public void dispatchViewManagerCommand(int reactTag, int commandId, @Nullable ReadableArray commandArgs) {
mUIImplementation.dispatchViewManagerCommand(reactTag, commandId, 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 @ReactMethod

View File

@ -647,7 +647,7 @@ public class UIViewOperationQueue {
public void enqueueDispatchCommand( public void enqueueDispatchCommand(
int reactTag, int reactTag,
int commandId, int commandId,
ReadableArray commandArgs) { @Nullable ReadableArray commandArgs) {
mOperations.add(new DispatchCommandOperation(reactTag, commandId, commandArgs)); mOperations.add(new DispatchCommandOperation(reactTag, commandId, commandArgs));
} }