Enable NativeAnimationDriver in Fabric

Summary:
Enables NativeAnimationDriver in Fabric.

Fabric animations:
{F151048224}

Pre-Fabric animations:

{F151048344}

Reviewed By: mdvacca

Differential Revision: D14114388

fbshipit-source-id: 1f64db168ae037535a31def7da28b9e0474b7198
This commit is contained in:
Joshua Gross
2019-02-20 00:15:04 -08:00
committed by Facebook Github Bot
parent a89fe4165c
commit ab6ea9c938
8 changed files with 207 additions and 185 deletions
@@ -19,7 +19,6 @@ import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.uimanager.IllegalViewOperationException;
import com.facebook.react.uimanager.UIImplementation;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.EventDispatcherListener;
@@ -57,13 +56,13 @@ import javax.annotation.Nullable;
// there will be only one driver per mapping so all code code should be optimized around that.
private final Map<String, List<EventAnimationDriver>> mEventDrivers = new HashMap<>();
private final UIManagerModule.CustomEventNamesResolver mCustomEventNamesResolver;
private final UIImplementation mUIImplementation;
private final UIManagerModule mUIManagerModule;
private int mAnimatedGraphBFSColor = 0;
// Used to avoid allocating a new array on every frame in `runUpdates` and `onEventDispatch`.
private final List<AnimatedNode> mRunUpdateNodeList = new LinkedList<>();
public NativeAnimatedNodesManager(UIManagerModule uiManager) {
mUIImplementation = uiManager.getUIImplementation();
mUIManagerModule = uiManager;
uiManager.getEventDispatcher().addListener(this);
mCustomEventNamesResolver = uiManager.getDirectEventNamesResolver();
}
@@ -88,7 +87,7 @@ import javax.annotation.Nullable;
} else if ("value".equals(type)) {
node = new ValueAnimatedNode(config);
} else if ("props".equals(type)) {
node = new PropsAnimatedNode(config, this, mUIImplementation);
node = new PropsAnimatedNode(config, this, mUIManagerModule);
} else if ("interpolation".equals(type)) {
node = new InterpolationAnimatedNode(config);
} else if ("addition".equals(type)) {
@@ -11,9 +11,8 @@ import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.JavaOnlyMap;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.uimanager.ReactStylesDiffMap;
import com.facebook.react.uimanager.UIImplementation;
import com.facebook.react.bridge.UIManager;
import java.util.HashMap;
import java.util.Map;
@@ -28,14 +27,11 @@ import javax.annotation.Nullable;
private int mConnectedViewTag = -1;
private final NativeAnimatedNodesManager mNativeAnimatedNodesManager;
private final UIImplementation mUIImplementation;
private final UIManager mUIManager;
private final Map<String, Integer> mPropNodeMapping;
// This is the backing map for `mDiffMap` we can mutate this to update it instead of having to
// create a new one for each update.
private final JavaOnlyMap mPropMap;
private final ReactStylesDiffMap mDiffMap;
PropsAnimatedNode(ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager, UIImplementation uiImplementation) {
PropsAnimatedNode(ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager, UIManager uiManager) {
ReadableMap props = config.getMap("props");
ReadableMapKeySetIterator iter = props.keySetIterator();
mPropNodeMapping = new HashMap<>();
@@ -45,9 +41,8 @@ import javax.annotation.Nullable;
mPropNodeMapping.put(propKey, nodeIndex);
}
mPropMap = new JavaOnlyMap();
mDiffMap = new ReactStylesDiffMap(mPropMap);
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
mUIImplementation = uiImplementation;
mUIManager = uiManager;
}
public void connectToView(int viewTag) {
@@ -73,9 +68,9 @@ import javax.annotation.Nullable;
mPropMap.putNull(it.nextKey());
}
mUIImplementation.synchronouslyUpdateViewOnUIThread(
mUIManager.synchronouslyUpdateViewOnUIThread(
mConnectedViewTag,
mDiffMap);
mPropMap);
}
public final void updateView() {
@@ -96,8 +91,8 @@ import javax.annotation.Nullable;
}
}
mUIImplementation.synchronouslyUpdateViewOnUIThread(
mUIManager.synchronouslyUpdateViewOnUIThread(
mConnectedViewTag,
mDiffMap);
mPropMap);
}
}
@@ -7,7 +7,6 @@
package com.facebook.react.bridge;
import com.facebook.react.bridge.WritableMap;
import android.view.View;
import com.facebook.react.uimanager.common.MeasureSpecProvider;
import javax.annotation.Nullable;
@@ -44,4 +43,14 @@ public interface UIManager extends JSIModule, PerformanceCounter {
void clearJSResponder();
/**
* Used by native animated module to bypass the process of updating the values through the shadow
* view hierarchy. This method will directly update native views, which means that updates for
* layout-related propertied won't be handled properly.
* Make sure you know what you're doing before calling this method :)
*
* @param tag {@link int} that identifies the view that will be updated
* @param props {@link ReadableMap} props that should be immediately updated in view
*/
void synchronouslyUpdateViewOnUIThread(int reactTag, ReadableMap props);
}
@@ -53,6 +53,7 @@ import com.facebook.react.fabric.mounting.mountitems.UpdateLocalDataMountItem;
import com.facebook.react.fabric.mounting.mountitems.UpdatePropsMountItem;
import com.facebook.react.modules.core.ReactChoreographer;
import com.facebook.react.uimanager.ReactRootViewTagGenerator;
import com.facebook.react.uimanager.ReactStylesDiffMap;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewManagerPropertyUpdater;
import com.facebook.react.uimanager.ViewManagerRegistry;
@@ -273,6 +274,12 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
getYogaMeasureMode(minHeight, maxHeight));
}
@Override
public void synchronouslyUpdateViewOnUIThread(int reactTag, ReadableMap props) {
long time = SystemClock.uptimeMillis();
scheduleMountItems(updatePropsMountItem(reactTag, props), time, time, time);
}
/**
* This method enqueues UI operations directly to the UI thread. This might change in the future
* to enforce execution order using {@link ReactChoreographer#CallbackType}.
@@ -9,7 +9,9 @@ rn_android_library(
"events/*.java",
"layoutanimation/*.java",
],
exclude = ["DisplayMetricsHolder.java"],
exclude = [
"DisplayMetricsHolder.java",
],
),
provided_deps = [
react_native_dep("third-party/android/support/v4:lib-support-v4"),
@@ -39,7 +39,7 @@ import java.util.Set;
import javax.annotation.Nullable;
/**
* An class that is used to receive React commands from JS and translate them into a
* A class that is used to receive React commands from JS and translate them into a
* shadow node hierarchy that is then mapped to a native view hierarchy.
*/
public class UIImplementation {
@@ -9,6 +9,7 @@ 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.UIManagerType.DEFAULT;
import static com.facebook.react.uimanager.common.UIManagerType.FABRIC;
import android.content.ComponentCallbacks2;
import android.content.Context;
@@ -32,6 +33,7 @@ import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.UIManager;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.common.ReactConstants;
@@ -217,7 +219,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule
@Override
public void onHostResume() {
mUIImplementation.onHostResume();
}
@@ -381,6 +382,23 @@ public class UIManagerModule extends ReactContextBaseJavaModule
return addRootView(rootView, null, null);
}
/**
* Used by native animated module to bypass the process of updating the values through the shadow
* view hierarchy. This method will directly update native views, which means that updates for
* layout-related propertied won't be handled properly.
* Make sure you know what you're doing before calling this method :)
*/
@Override
public void synchronouslyUpdateViewOnUIThread(int tag, ReadableMap props) {
int uiManagerType = ViewUtil.getUIManagerType(tag);
if (uiManagerType == FABRIC) {
UIManager fabricUIManager = UIManagerHelper.getUIManager(getReactApplicationContext(), uiManagerType);
fabricUIManager.synchronouslyUpdateViewOnUIThread(tag, props);
} else {
mUIImplementation.synchronouslyUpdateViewOnUIThread(tag, new ReactStylesDiffMap(props));
}
}
/**
* Registers a new root view. JS can use the returned tag with manageChildren to add/remove
* children to this view.
@@ -455,6 +473,7 @@ public class UIManagerModule extends ReactContextBaseJavaModule
FLog.d(ReactConstants.TAG, message);
PrinterHolder.getPrinter().logMessage(ReactDebugOverlayTags.UI_MANAGER, message);
}
mUIImplementation.updateView(tag, className, props);
}