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.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();

View File

@ -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,9 +403,8 @@ public class ReactRootView extends SizeMonitoringFrameLayout
new GuardedRunnable(reactApplicationContext) {
@Override
public void runGuarded() {
reactApplicationContext
.getCatalystInstance()
.getNativeModule(UIManagerModule.class)
UIManagerHelper
.getUIManager(reactApplicationContext, isFabric())
.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.SizeMonitoringFrameLayout;
import javax.annotation.Nullable;
public interface UIManager extends JSIModule {
/**
@ -10,4 +12,19 @@ public interface UIManager extends JSIModule {
*/
<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.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.
*

View File

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

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_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,10 +586,18 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
mUIImplementation.clearJSResponder();
}
@Override
@ReactMethod
public void dispatchViewManagerCommand(int reactTag, int commandId, ReadableArray 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
public void playTouchSound() {

View File

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