From ab6ea9c938cc6e0d0c781a25c2496acbdf835b11 Mon Sep 17 00:00:00 2001 From: Joshua Gross Date: Wed, 20 Feb 2019 00:12:12 -0800 Subject: [PATCH] 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 --- .../animated/NativeAnimatedNodesManager.java | 7 +- .../react/animated/PropsAnimatedNode.java | 21 +- .../com/facebook/react/bridge/UIManager.java | 11 +- .../react/fabric/FabricUIManager.java | 7 + .../java/com/facebook/react/uimanager/BUCK | 4 +- .../react/uimanager/UIImplementation.java | 2 +- .../react/uimanager/UIManagerModule.java | 21 +- .../NativeAnimatedNodeTraversalTest.java | 319 +++++++++--------- 8 files changed, 207 insertions(+), 185 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java index 41d2746e077..1dff9639cdd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java @@ -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> 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 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)) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/PropsAnimatedNode.java b/ReactAndroid/src/main/java/com/facebook/react/animated/PropsAnimatedNode.java index d59a05aa953..250eb21dbc0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/PropsAnimatedNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/PropsAnimatedNode.java @@ -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 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); } } 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 f435185a48b..15949bbce9f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java @@ -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); } 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 3bae4836e4b..8f58ea15151 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -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}. diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK index b1279ccd9ba..f707ac49c32 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK @@ -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"), 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 b81c517976f..d8fcc91a172 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java @@ -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 { 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 c3f16527a26..5af84191c36 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -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); } diff --git a/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.java b/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.java index 6e12db5c415..91037f899c4 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.java @@ -13,7 +13,6 @@ import com.facebook.react.bridge.JavaOnlyArray; import com.facebook.react.bridge.JavaOnlyMap; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.common.MapBuilder; -import com.facebook.react.uimanager.ReactStylesDiffMap; import com.facebook.react.uimanager.UIImplementation; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.events.Event; @@ -62,7 +61,6 @@ public class NativeAnimatedNodeTraversalTest { private long mFrameTimeNanos; private UIManagerModule mUIManagerMock; - private UIImplementation mUIImplementationMock; private EventDispatcher mEventDispatcherMock; private NativeAnimatedNodesManager mNativeAnimatedNodesManager; @@ -88,14 +86,7 @@ public class NativeAnimatedNodeTraversalTest { mFrameTimeNanos = INITIAL_FRAME_TIME_NANOS; mUIManagerMock = mock(UIManagerModule.class); - mUIImplementationMock = mock(UIImplementation.class); mEventDispatcherMock = mock(EventDispatcher.class); - PowerMockito.when(mUIManagerMock.getUIImplementation()).thenAnswer(new Answer() { - @Override - public UIImplementation answer(InvocationOnMock invocation) throws Throwable { - return mUIImplementationMock; - } - }); PowerMockito.when(mUIManagerMock.getEventDispatcher()).thenAnswer(new Answer() { @Override public EventDispatcher answer(InvocationOnMock invocation) throws Throwable { @@ -166,21 +157,21 @@ public class NativeAnimatedNodeTraversalTest { JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 1d), animationCallback); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); for (int i = 0; i < frames.size(); i++) { - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock) + verify(mUIManagerMock) .synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("opacity", Double.NaN)) + assertThat(stylesCaptor.getValue().getDouble("opacity")) .isEqualTo(frames.getDouble(i)); } - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); } @Test @@ -195,23 +186,23 @@ public class NativeAnimatedNodeTraversalTest { JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 1d, "iterations", 5), animationCallback); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); for (int iteration = 0; iteration < 5; iteration++) { for (int i = 0; i < frames.size(); i++) { - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock) + verify(mUIManagerMock) .synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("opacity", Double.NaN)) + assertThat(stylesCaptor.getValue().getDouble("opacity")) .isEqualTo(frames.getDouble(i)); } } - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); } @Test @@ -279,23 +270,23 @@ public class NativeAnimatedNodeTraversalTest { config, animationCallback); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("opacity", Double.NaN)).isEqualTo(0); + verify(mUIManagerMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); + assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(0); double previousValue = 0d; boolean wasGreaterThanOne = false; /* run 3 secs of animation */ for (int i = 0; i < 3 * 60; i++) { - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock, atMost(1)) + verify(mUIManagerMock, atMost(1)) .synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - double currentValue = stylesCaptor.getValue().getDouble("opacity", Double.NaN); + double currentValue = stylesCaptor.getValue().getDouble("opacity"); if (currentValue > 1d) { wasGreaterThanOne = true; } @@ -311,9 +302,9 @@ public class NativeAnimatedNodeTraversalTest { } else { assertThat(wasGreaterThanOne); } - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); } @Test @@ -402,13 +393,13 @@ public class NativeAnimatedNodeTraversalTest { ), animationCallback); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("opacity", Double.NaN)).isEqualTo(0); + verify(mUIManagerMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); + assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(0); double previousValue = 0d; boolean wasGreaterThanOne = false; @@ -416,11 +407,11 @@ public class NativeAnimatedNodeTraversalTest { int numberOfResets = 0; /* run 3 secs of animation, five times */ for (int i = 0; i < 3 * 60 * 5; i++) { - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock, atMost(1)) + verify(mUIManagerMock, atMost(1)) .synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - double currentValue = stylesCaptor.getValue().getDouble("opacity", Double.NaN); + double currentValue = stylesCaptor.getValue().getDouble("opacity"); if (currentValue > 1d) { wasGreaterThanOne = true; } @@ -446,9 +437,9 @@ public class NativeAnimatedNodeTraversalTest { assertThat(wasGreaterThanOne); // verify that value reset 4 times after finishing a full animation assertThat(numberOfResets).isEqualTo(4); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); } @Test @@ -468,22 +459,22 @@ public class NativeAnimatedNodeTraversalTest { 0.998d), animationCallback); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock, atMost(1)) + verify(mUIManagerMock, atMost(1)) .synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - double previousValue = stylesCaptor.getValue().getDouble("opacity", Double.NaN); + double previousValue = stylesCaptor.getValue().getDouble("opacity"); double previousDiff = Double.POSITIVE_INFINITY; /* run 3 secs of animation */ for (int i = 0; i < 3 * 60; i++) { - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock, atMost(1)) + verify(mUIManagerMock, atMost(1)) .synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - double currentValue = stylesCaptor.getValue().getDouble("opacity", Double.NaN); + double currentValue = stylesCaptor.getValue().getDouble("opacity"); double currentDiff = currentValue - previousValue; // verify monotonicity // greater *or equal* because the animation stops during these 3 seconds @@ -503,9 +494,9 @@ public class NativeAnimatedNodeTraversalTest { previousDiff = currentDiff; } // should be done in 3s - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); } @Test @@ -527,25 +518,25 @@ public class NativeAnimatedNodeTraversalTest { 5), animationCallback); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock, atMost(1)) + verify(mUIManagerMock, atMost(1)) .synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - double previousValue = stylesCaptor.getValue().getDouble("opacity", Double.NaN); + double previousValue = stylesCaptor.getValue().getDouble("opacity"); double previousDiff = Double.POSITIVE_INFINITY; - double initialValue = stylesCaptor.getValue().getDouble("opacity", Double.NaN); + double initialValue = stylesCaptor.getValue().getDouble("opacity"); boolean didComeToRest = false; int numberOfResets = 0; /* run 3 secs of animation, five times */ for (int i = 0; i < 3 * 60 * 5; i++) { - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock, atMost(1)) + verify(mUIManagerMock, atMost(1)) .synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - double currentValue = stylesCaptor.getValue().getDouble("opacity", Double.NaN); + double currentValue = stylesCaptor.getValue().getDouble("opacity"); double currentDiff = currentValue - previousValue; // Test to see if it reset after coming to rest (i.e. dropped back to ) if (didComeToRest && currentValue == initialValue) { @@ -564,9 +555,9 @@ public class NativeAnimatedNodeTraversalTest { // verify that value reset (looped) 4 times after finishing a full animation assertThat(numberOfResets).isEqualTo(4); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); } @Test @@ -653,23 +644,23 @@ public class NativeAnimatedNodeTraversalTest { JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 1010d), animationCallback); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(1100d); + verify(mUIManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); + assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(1100d); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock) + verify(mUIManagerMock) .synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(1111d); + assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(1111d); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); } /** @@ -692,23 +683,23 @@ public class NativeAnimatedNodeTraversalTest { JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 101d), animationCallback); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(1100d); + verify(mUIManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); + assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(1100d); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock) + verify(mUIManagerMock) .synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(1101d); + assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(1101d); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); } /** @@ -741,26 +732,26 @@ public class NativeAnimatedNodeTraversalTest { JavaOnlyMap.of("type", "frames", "frames", secondFrames, "toValue", 1010d), animationCallback); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(1100d); + verify(mUIManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); + assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(1100d); for (int i = 1; i < secondFrames.size(); i++) { - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock) + verify(mUIManagerMock) .synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)) + assertThat(stylesCaptor.getValue().getDouble("translateX")) .isEqualTo(1200d + secondFrames.getDouble(i) * 10d); } - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); } @Test @@ -802,22 +793,22 @@ public class NativeAnimatedNodeTraversalTest { JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 10d), animationCallback); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(5d); + verify(mUIManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); + assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(5d); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(20d); + verify(mUIManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); + assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(20d); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); } /** @@ -840,32 +831,32 @@ public class NativeAnimatedNodeTraversalTest { ArgumentCaptor callbackResponseCaptor = ArgumentCaptor.forClass(ReadableMap.class); reset(animationCallback); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock, times(2)) - .synchronouslyUpdateViewOnUIThread(anyInt(), any(ReactStylesDiffMap.class)); + verify(mUIManagerMock, times(2)) + .synchronouslyUpdateViewOnUIThread(anyInt(), any(ReadableMap.class)); verifyNoMoreInteractions(animationCallback); reset(animationCallback); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.stopAnimation(404); verify(animationCallback).invoke(callbackResponseCaptor.capture()); verifyNoMoreInteractions(animationCallback); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); assertThat(callbackResponseCaptor.getValue().hasKey("finished")).isTrue(); assertThat(callbackResponseCaptor.getValue().getBoolean("finished")).isFalse(); reset(animationCallback); - reset(mUIImplementationMock); + reset(mUIManagerMock); // Run "update" loop a few more times -> we expect no further updates nor callback calls to be // triggered for (int i = 0; i < 5; i++) { mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); } - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); verifyNoMoreInteractions(animationCallback); } @@ -908,21 +899,21 @@ public class NativeAnimatedNodeTraversalTest { JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 20d), animationCallback); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); for (int i = 0; i < frames.size(); i++) { - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock) + verify(mUIManagerMock) .synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("opacity", Double.NaN)) + assertThat(stylesCaptor.getValue().getDouble("opacity")) .isEqualTo(frames.getDouble(i)); } - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); } private Event createScrollEvent(final int tag, final double value) { @@ -952,13 +943,13 @@ public class NativeAnimatedNodeTraversalTest { mNativeAnimatedNodesManager.onEventDispatch(createScrollEvent(viewTag, 10)); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("opacity", Double.NaN)).isEqualTo(10); + verify(mUIManagerMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture()); + assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(10); } @Test @@ -977,13 +968,13 @@ public class NativeAnimatedNodeTraversalTest { mNativeAnimatedNodesManager.onEventDispatch(createScrollEvent(viewTag, 10)); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("opacity", Double.NaN)).isEqualTo(0); + verify(mUIManagerMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture()); + assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(0); } @Test @@ -1008,13 +999,13 @@ public class NativeAnimatedNodeTraversalTest { mNativeAnimatedNodesManager.onEventDispatch(createScrollEvent(viewTag, 10)); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("opacity", Double.NaN)).isEqualTo(10); + verify(mUIManagerMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture()); + assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(10); } @Test @@ -1042,20 +1033,20 @@ public class NativeAnimatedNodeTraversalTest { JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 0d), animationCallback); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); for (int i = 0; i < frames.size(); i++) { - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); } - verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("opacity", Double.NaN)).isEqualTo(0); + verify(mUIManagerMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture()); + assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(0); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.restoreDefaultValues(propsNodeTag, viewTag); - verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture()); + verify(mUIManagerMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture()); assertThat(stylesCaptor.getValue().isNull("opacity")); } @@ -1105,24 +1096,24 @@ public class NativeAnimatedNodeTraversalTest { createAnimatedGraphWithTrackingNode(1000, 0d, animationConfig); - ArgumentCaptor stylesCaptor = - ArgumentCaptor.forClass(ReactStylesDiffMap.class); + ArgumentCaptor stylesCaptor = + ArgumentCaptor.forClass(ReadableMap.class); - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(0d); + verify(mUIManagerMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); + assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(0d); // update "toValue" to 100, we expect tracking animation to animate now from 0 to 100 in 5 steps mNativeAnimatedNodesManager.setAnimatedNodeValue(1, 100d); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); // kick off the animation for (int i = 0; i < frames.size(); i++) { - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock) + verify(mUIManagerMock) .synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)) + assertThat(stylesCaptor.getValue().getDouble("translateX")) .isEqualTo(frames.getDouble(i) * 100d); } @@ -1132,11 +1123,11 @@ public class NativeAnimatedNodeTraversalTest { mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); // kick off the animation for (int i = 0; i < 2; i++) { - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock) + verify(mUIManagerMock) .synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)) + assertThat(stylesCaptor.getValue().getDouble("translateX")) .isEqualTo(100d * (1d - frames.getDouble(i))); } @@ -1149,11 +1140,11 @@ public class NativeAnimatedNodeTraversalTest { mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); // kick off the animation for (int i = 0; i < frames.size(); i++) { - reset(mUIImplementationMock); + reset(mUIManagerMock); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verify(mUIImplementationMock) + verify(mUIManagerMock) .synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture()); - assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)) + assertThat(stylesCaptor.getValue().getDouble("translateX")) .isEqualTo(50d + 50d * frames.getDouble(i)); } } @@ -1174,38 +1165,38 @@ public class NativeAnimatedNodeTraversalTest { mNativeAnimatedNodesManager.setAnimatedNodeValue(1, 100d); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); // make sure animation starts - reset(mUIImplementationMock); + reset(mUIManagerMock); for (int i = 0; i < frames.size(); i++) { assertThat(mNativeAnimatedNodesManager.hasActiveAnimations()).isTrue(); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); } - verify(mUIImplementationMock, times(frames.size())) - .synchronouslyUpdateViewOnUIThread(eq(1000), any(ReactStylesDiffMap.class)); + verify(mUIManagerMock, times(frames.size())) + .synchronouslyUpdateViewOnUIThread(eq(1000), any(ReadableMap.class)); // the animation has completed, we expect no updates to be done - reset(mUIImplementationMock); + reset(mUIManagerMock); assertThat(mNativeAnimatedNodesManager.hasActiveAnimations()).isFalse(); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); // we update end value and expect the animation to restart mNativeAnimatedNodesManager.setAnimatedNodeValue(1, 200d); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); // make sure animation starts - reset(mUIImplementationMock); + reset(mUIManagerMock); for (int i = 0; i < frames.size(); i++) { assertThat(mNativeAnimatedNodesManager.hasActiveAnimations()).isTrue(); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); } - verify(mUIImplementationMock, times(frames.size())) - .synchronouslyUpdateViewOnUIThread(eq(1000), any(ReactStylesDiffMap.class)); + verify(mUIManagerMock, times(frames.size())) + .synchronouslyUpdateViewOnUIThread(eq(1000), any(ReadableMap.class)); // the animation has completed, we expect no updates to be done - reset(mUIImplementationMock); + reset(mUIManagerMock); assertThat(mNativeAnimatedNodesManager.hasActiveAnimations()).isFalse(); mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); - verifyNoMoreInteractions(mUIImplementationMock); + verifyNoMoreInteractions(mUIManagerMock); } /**