mirror of
https://github.com/status-im/react-native.git
synced 2025-02-05 14:13:26 +00:00
support api 15 (use Handler-backed ui driven).
Summary: Android API 15 still have 1.5~2.0% distribution (refer: [Dashboard - Android Developer](https://developer.android.com/ndk/guides/standalone_toolchain.html#creating_the_toolchain)). React Native is a good tec but many companies cannot endure loose their consumer. [Choreographer](https://developer.android.com/reference/android/view/Choreographer.html) triggered UI operation is the only reason that React Native Android sdk use minSdkVersion 16, so we can use a backward solution **only in API 15**: [Handler](https://developer.android.com/reference/android/os/Handler.html). In this PR, the biggest change is : - Make core operation of ReactChoreographer to an interface: ReactUIDriver; - Impl ReactUIDriver by Handler => UIDriverHandlerImpl, refactor ReactChoreographer to UIDriverChoreographerImpl; - Let UIDriverFactory to choose which one impl would be in use. (Only use handler in api 15). Closes https://github.com/facebook/react-native/pull/12396 Reviewed By: AaaChiuuu Differential Revision: D4588399 Pulled By: astreet fbshipit-source-id: 76408e53664314dd926e6a553cde6bafbd37779e
This commit is contained in:
parent
8b01508410
commit
20ad2b3fbb
@ -14,10 +14,10 @@ import java.util.concurrent.TimeUnit;
|
||||
import android.app.Instrumentation;
|
||||
import android.os.SystemClock;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.view.Choreographer;
|
||||
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.modules.core.ChoreographerCompat;
|
||||
|
||||
public class ReactIdleDetectionUtil {
|
||||
|
||||
@ -56,8 +56,8 @@ public class ReactIdleDetectionUtil {
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Choreographer.getInstance().postFrameCallback(
|
||||
new Choreographer.FrameCallback() {
|
||||
ChoreographerCompat.getInstance().postFrameCallback(
|
||||
new ChoreographerCompat.FrameCallback() {
|
||||
|
||||
private int frameCount = 0;
|
||||
|
||||
@ -67,7 +67,7 @@ public class ReactIdleDetectionUtil {
|
||||
if (frameCount == waitFrameCount) {
|
||||
latch.countDown();
|
||||
} else {
|
||||
Choreographer.getInstance().postFrameCallback(this);
|
||||
ChoreographerCompat.getInstance().postFrameCallback(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -23,8 +23,8 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
||||
import com.facebook.react.uimanager.GuardedChoreographerFrameCallback;
|
||||
import com.facebook.react.modules.core.ReactChoreographer;
|
||||
import com.facebook.react.uimanager.GuardedFrameCallback;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -79,7 +79,7 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
|
||||
}
|
||||
|
||||
private final Object mOperationsCopyLock = new Object();
|
||||
private @Nullable GuardedChoreographerFrameCallback mAnimatedFrameCallback;
|
||||
private @Nullable GuardedFrameCallback mAnimatedFrameCallback;
|
||||
private @Nullable ReactChoreographer mReactChoreographer;
|
||||
private ArrayList<UIThreadOperation> mOperations = new ArrayList<>();
|
||||
private volatile @Nullable ArrayList<UIThreadOperation> mReadyOperations = null;
|
||||
@ -97,7 +97,7 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
|
||||
UIManagerModule uiManager = reactCtx.getNativeModule(UIManagerModule.class);
|
||||
|
||||
final NativeAnimatedNodesManager nodesManager = new NativeAnimatedNodesManager(uiManager);
|
||||
mAnimatedFrameCallback = new GuardedChoreographerFrameCallback(reactCtx) {
|
||||
mAnimatedFrameCallback = new GuardedFrameCallback(reactCtx) {
|
||||
@Override
|
||||
protected void doFrameGuarded(final long frameTimeNanos) {
|
||||
|
||||
|
@ -19,6 +19,7 @@ android_library(
|
||||
react_native_target("java/com/facebook/react/common/network:network"),
|
||||
react_native_target("java/com/facebook/react/devsupport:interfaces"),
|
||||
react_native_target("java/com/facebook/react/module/annotations:annotations"),
|
||||
react_native_target('java/com/facebook/react/modules/core:core'),
|
||||
react_native_target("java/com/facebook/react/modules/debug:debug"),
|
||||
react_native_target("java/com/facebook/react/modules/debug:interfaces"),
|
||||
react_native_target("java/com/facebook/react/modules/systeminfo:systeminfo"),
|
||||
|
@ -12,7 +12,6 @@ package com.facebook.react.devsupport;
|
||||
import java.util.Locale;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.view.Choreographer;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -20,6 +19,7 @@ import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.R;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.modules.core.ChoreographerCompat;
|
||||
import com.facebook.react.modules.debug.FpsDebugFrameCallback;
|
||||
|
||||
/**
|
||||
@ -41,7 +41,7 @@ public class FpsView extends FrameLayout {
|
||||
super(reactContext);
|
||||
inflate(reactContext, R.layout.fps_view, this);
|
||||
mTextView = (TextView) findViewById(R.id.fps_text);
|
||||
mFrameCallback = new FpsDebugFrameCallback(Choreographer.getInstance(), reactContext);
|
||||
mFrameCallback = new FpsDebugFrameCallback(ChoreographerCompat.getInstance(), reactContext);
|
||||
mFPSMonitorRunnable = new FPSMonitorRunnable();
|
||||
setCurrentFPS(0, 0, 0, 0);
|
||||
}
|
||||
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* This file was pulled from the facebook/rebound repository.
|
||||
*/
|
||||
package com.facebook.react.modules.core;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.Choreographer;
|
||||
|
||||
/**
|
||||
* Wrapper class for abstracting away availability of the JellyBean Choreographer. If Choreographer
|
||||
* is unavailable we fallback to using a normal Handler.
|
||||
*/
|
||||
public class ChoreographerCompat {
|
||||
|
||||
private static final long ONE_FRAME_MILLIS = 17;
|
||||
private static final boolean IS_JELLYBEAN_OR_HIGHER =
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
|
||||
private static final ChoreographerCompat INSTANCE = new ChoreographerCompat();
|
||||
|
||||
private Handler mHandler;
|
||||
private Choreographer mChoreographer;
|
||||
|
||||
public static ChoreographerCompat getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private ChoreographerCompat() {
|
||||
if (IS_JELLYBEAN_OR_HIGHER) {
|
||||
mChoreographer = getChoreographer();
|
||||
} else {
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
}
|
||||
|
||||
public void postFrameCallback(FrameCallback callbackWrapper) {
|
||||
if (IS_JELLYBEAN_OR_HIGHER) {
|
||||
choreographerPostFrameCallback(callbackWrapper.getFrameCallback());
|
||||
} else {
|
||||
mHandler.postDelayed(callbackWrapper.getRunnable(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void postFrameCallbackDelayed(FrameCallback callbackWrapper, long delayMillis) {
|
||||
if (IS_JELLYBEAN_OR_HIGHER) {
|
||||
choreographerPostFrameCallbackDelayed(callbackWrapper.getFrameCallback(), delayMillis);
|
||||
} else {
|
||||
mHandler.postDelayed(callbackWrapper.getRunnable(), delayMillis + ONE_FRAME_MILLIS);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeFrameCallback(FrameCallback callbackWrapper) {
|
||||
if (IS_JELLYBEAN_OR_HIGHER) {
|
||||
choreographerRemoveFrameCallback(callbackWrapper.getFrameCallback());
|
||||
} else {
|
||||
mHandler.removeCallbacks(callbackWrapper.getRunnable());
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
private Choreographer getChoreographer() {
|
||||
return Choreographer.getInstance();
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
private void choreographerPostFrameCallback(Choreographer.FrameCallback frameCallback) {
|
||||
mChoreographer.postFrameCallback(frameCallback);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
private void choreographerPostFrameCallbackDelayed(
|
||||
Choreographer.FrameCallback frameCallback,
|
||||
long delayMillis) {
|
||||
mChoreographer.postFrameCallbackDelayed(frameCallback, delayMillis);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
private void choreographerRemoveFrameCallback(Choreographer.FrameCallback frameCallback) {
|
||||
mChoreographer.removeFrameCallback(frameCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* This class provides a compatibility wrapper around the JellyBean FrameCallback with methods
|
||||
* to access cached wrappers for submitting a real FrameCallback to a Choreographer or a Runnable
|
||||
* to a Handler.
|
||||
*/
|
||||
public static abstract class FrameCallback {
|
||||
|
||||
private Runnable mRunnable;
|
||||
private Choreographer.FrameCallback mFrameCallback;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
Choreographer.FrameCallback getFrameCallback() {
|
||||
if (mFrameCallback == null) {
|
||||
mFrameCallback = new Choreographer.FrameCallback() {
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
FrameCallback.this.doFrame(frameTimeNanos);
|
||||
}
|
||||
};
|
||||
}
|
||||
return mFrameCallback;
|
||||
}
|
||||
|
||||
Runnable getRunnable() {
|
||||
if (mRunnable == null) {
|
||||
mRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doFrame(System.nanoTime());
|
||||
}
|
||||
};
|
||||
}
|
||||
return mRunnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Just a wrapper for frame callback, see {@link android.view.Choreographer.FrameCallback#doFrame(long)}.
|
||||
*/
|
||||
public abstract void doFrame(long frameTimeNanos);
|
||||
}
|
||||
}
|
@ -11,8 +11,6 @@ package com.facebook.react.modules.core;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
import android.view.Choreographer;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
@ -25,7 +23,7 @@ import com.facebook.react.common.ReactConstants;
|
||||
*/
|
||||
public class ReactChoreographer {
|
||||
|
||||
public static enum CallbackType {
|
||||
public enum CallbackType {
|
||||
|
||||
/**
|
||||
* For use by perf markers that need to happen immediately after draw
|
||||
@ -75,15 +73,15 @@ public class ReactChoreographer {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private final Choreographer mChoreographer;
|
||||
private final ChoreographerCompat mChoreographer;
|
||||
private final ReactChoreographerDispatcher mReactChoreographerDispatcher;
|
||||
private final ArrayDeque<Choreographer.FrameCallback>[] mCallbackQueues;
|
||||
private final ArrayDeque<ChoreographerCompat.FrameCallback>[] mCallbackQueues;
|
||||
|
||||
private int mTotalCallbacks = 0;
|
||||
private boolean mHasPostedCallback = false;
|
||||
|
||||
private ReactChoreographer() {
|
||||
mChoreographer = Choreographer.getInstance();
|
||||
mChoreographer = ChoreographerCompat.getInstance();
|
||||
mReactChoreographerDispatcher = new ReactChoreographerDispatcher();
|
||||
mCallbackQueues = new ArrayDeque[CallbackType.values().length];
|
||||
for (int i = 0; i < mCallbackQueues.length; i++) {
|
||||
@ -91,7 +89,7 @@ public class ReactChoreographer {
|
||||
}
|
||||
}
|
||||
|
||||
public void postFrameCallback(CallbackType type, Choreographer.FrameCallback frameCallback) {
|
||||
public void postFrameCallback(CallbackType type, ChoreographerCompat.FrameCallback frameCallback) {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
mCallbackQueues[type.getOrder()].addLast(frameCallback);
|
||||
mTotalCallbacks++;
|
||||
@ -102,7 +100,7 @@ public class ReactChoreographer {
|
||||
}
|
||||
}
|
||||
|
||||
public void removeFrameCallback(CallbackType type, Choreographer.FrameCallback frameCallback) {
|
||||
public void removeFrameCallback(CallbackType type, ChoreographerCompat.FrameCallback frameCallback) {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
if (mCallbackQueues[type.getOrder()].removeFirstOccurrence(frameCallback)) {
|
||||
mTotalCallbacks--;
|
||||
@ -120,7 +118,7 @@ public class ReactChoreographer {
|
||||
}
|
||||
}
|
||||
|
||||
private class ReactChoreographerDispatcher implements Choreographer.FrameCallback {
|
||||
private class ReactChoreographerDispatcher extends ChoreographerCompat.FrameCallback {
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
|
@ -22,7 +22,6 @@ import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import android.util.SparseArray;
|
||||
import android.view.Choreographer;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
@ -81,7 +80,7 @@ public final class Timing extends ReactContextBaseJavaModule implements Lifecycl
|
||||
}
|
||||
}
|
||||
|
||||
private class TimerFrameCallback implements Choreographer.FrameCallback {
|
||||
private class TimerFrameCallback extends ChoreographerCompat.FrameCallback {
|
||||
|
||||
// Temporary map for constructing the individual arrays of timers per ExecutorToken
|
||||
private final HashMap<ExecutorToken, WritableArray> mTimersToCall = new HashMap<>();
|
||||
@ -131,7 +130,7 @@ public final class Timing extends ReactContextBaseJavaModule implements Lifecycl
|
||||
}
|
||||
}
|
||||
|
||||
private class IdleFrameCallback implements Choreographer.FrameCallback {
|
||||
private class IdleFrameCallback extends ChoreographerCompat.FrameCallback {
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
@ -248,14 +247,14 @@ public final class Timing extends ReactContextBaseJavaModule implements Lifecycl
|
||||
@Override
|
||||
public void onHostPause() {
|
||||
isPaused.set(true);
|
||||
clearChoreographerCallback();
|
||||
maybeClearChoreographerIdleCallback();
|
||||
clearFrameCallback();
|
||||
maybeIdleCallback();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHostDestroy() {
|
||||
clearChoreographerCallback();
|
||||
maybeClearChoreographerIdleCallback();
|
||||
clearFrameCallback();
|
||||
maybeIdleCallback();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -281,14 +280,14 @@ public final class Timing extends ReactContextBaseJavaModule implements Lifecycl
|
||||
HeadlessJsTaskContext.getInstance(getReactApplicationContext());
|
||||
if (!headlessJsTaskContext.hasActiveTasks()) {
|
||||
isRunningTasks.set(false);
|
||||
clearChoreographerCallback();
|
||||
maybeClearChoreographerIdleCallback();
|
||||
clearFrameCallback();
|
||||
maybeIdleCallback();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCatalystInstanceDestroy() {
|
||||
clearChoreographerCallback();
|
||||
clearFrameCallback();
|
||||
clearChoreographerIdleCallback();
|
||||
HeadlessJsTaskContext headlessJsTaskContext =
|
||||
HeadlessJsTaskContext.getInstance(getReactApplicationContext());
|
||||
@ -303,9 +302,9 @@ public final class Timing extends ReactContextBaseJavaModule implements Lifecycl
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeClearChoreographerIdleCallback() {
|
||||
private void maybeIdleCallback() {
|
||||
if (isPaused.get() && !isRunningTasks.get()) {
|
||||
clearChoreographerCallback();
|
||||
clearFrameCallback();
|
||||
}
|
||||
}
|
||||
|
||||
@ -318,7 +317,7 @@ public final class Timing extends ReactContextBaseJavaModule implements Lifecycl
|
||||
}
|
||||
}
|
||||
|
||||
private void clearChoreographerCallback() {
|
||||
private void clearFrameCallback() {
|
||||
HeadlessJsTaskContext headlessJsTaskContext =
|
||||
HeadlessJsTaskContext.getInstance(getReactApplicationContext());
|
||||
if (mFrameCallbackPosted && isPaused.get() &&
|
||||
|
@ -13,8 +13,6 @@ import javax.annotation.Nullable;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import android.os.Build;
|
||||
import android.view.Choreographer;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
@ -24,6 +22,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.modules.core.ChoreographerCompat;
|
||||
import com.facebook.react.modules.debug.interfaces.DeveloperSettings;
|
||||
|
||||
/**
|
||||
@ -60,10 +59,9 @@ public class AnimationsDebugModule extends ReactContextBaseJavaModule {
|
||||
if (mFrameCallback != null) {
|
||||
throw new JSApplicationCausedNativeException("Already recording FPS!");
|
||||
}
|
||||
checkAPILevel();
|
||||
|
||||
mFrameCallback = new FpsDebugFrameCallback(
|
||||
Choreographer.getInstance(),
|
||||
ChoreographerCompat.getInstance(),
|
||||
getReactApplicationContext());
|
||||
mFrameCallback.startAndRecordFpsAtEachFrame();
|
||||
}
|
||||
@ -78,7 +76,6 @@ public class AnimationsDebugModule extends ReactContextBaseJavaModule {
|
||||
if (mFrameCallback == null) {
|
||||
return;
|
||||
}
|
||||
checkAPILevel();
|
||||
|
||||
mFrameCallback.stop();
|
||||
|
||||
@ -116,11 +113,4 @@ public class AnimationsDebugModule extends ReactContextBaseJavaModule {
|
||||
mFrameCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkAPILevel() {
|
||||
if (Build.VERSION.SDK_INT < 16) {
|
||||
throw new JSApplicationCausedNativeException(
|
||||
"Animation debugging is not supported in API <16");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ android_library(
|
||||
react_native_target("java/com/facebook/react/bridge:bridge"),
|
||||
react_native_target("java/com/facebook/react/common:common"),
|
||||
react_native_target("java/com/facebook/react/module/annotations:annotations"),
|
||||
react_native_target('java/com/facebook/react/modules/core:core'),
|
||||
react_native_target("java/com/facebook/react/modules/debug:interfaces"),
|
||||
react_native_target("java/com/facebook/react/uimanager:uimanager"),
|
||||
],
|
||||
|
@ -9,11 +9,10 @@
|
||||
|
||||
package com.facebook.react.modules.debug;
|
||||
|
||||
import android.view.Choreographer;
|
||||
|
||||
import com.facebook.react.bridge.ReactBridge;
|
||||
import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener;
|
||||
import com.facebook.react.common.LongArray;
|
||||
import com.facebook.react.modules.core.ChoreographerCompat;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.debug.NotThreadSafeViewHierarchyUpdateDebugListener;
|
||||
|
||||
@ -22,7 +21,7 @@ import com.facebook.react.uimanager.debug.NotThreadSafeViewHierarchyUpdateDebugL
|
||||
* to calculate whether JS was able to update the UI during a given frame. After being installed
|
||||
* on a {@link ReactBridge} and a {@link UIManagerModule},
|
||||
* {@link #getDidJSHitFrameAndCleanup} should be called once per frame via a
|
||||
* {@link Choreographer.FrameCallback}.
|
||||
* {@link ChoreographerCompat.FrameCallback}.
|
||||
*/
|
||||
public class DidJSUpdateUiDuringFrameDetector implements NotThreadSafeBridgeIdleDebugListener,
|
||||
NotThreadSafeViewHierarchyUpdateDebugListener {
|
||||
@ -56,7 +55,7 @@ public class DidJSUpdateUiDuringFrameDetector implements NotThreadSafeBridgeIdle
|
||||
}
|
||||
|
||||
/**
|
||||
* Designed to be called from a {@link Choreographer.FrameCallback#doFrame} call.
|
||||
* Designed to be called from a {@link ChoreographerCompat.FrameCallback#doFrame} call.
|
||||
*
|
||||
* There are two 'success' cases that will cause {@link #getDidJSHitFrameAndCleanup} to
|
||||
* return true for a given frame:
|
||||
|
@ -14,10 +14,8 @@ import javax.annotation.Nullable;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.view.Choreographer;
|
||||
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.modules.core.ChoreographerCompat;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
|
||||
@ -30,11 +28,8 @@ import com.facebook.infer.annotation.Assertions;
|
||||
* Also records the JS FPS, i.e. the frames per second with which either JS updated the UI or was
|
||||
* idle and not trying to update the UI. This is different from the FPS above since JS rendering is
|
||||
* async.
|
||||
*
|
||||
* TargetApi 16 for use of Choreographer.
|
||||
*/
|
||||
@TargetApi(16)
|
||||
public class FpsDebugFrameCallback implements Choreographer.FrameCallback {
|
||||
public class FpsDebugFrameCallback extends ChoreographerCompat.FrameCallback {
|
||||
|
||||
public static class FpsInfo {
|
||||
|
||||
@ -66,7 +61,7 @@ public class FpsDebugFrameCallback implements Choreographer.FrameCallback {
|
||||
|
||||
private static final double EXPECTED_FRAME_TIME = 16.9;
|
||||
|
||||
private final Choreographer mChoreographer;
|
||||
private final ChoreographerCompat mChoreographer;
|
||||
private final ReactContext mReactContext;
|
||||
private final UIManagerModule mUIManagerModule;
|
||||
private final DidJSUpdateUiDuringFrameDetector mDidJSUpdateUiDuringFrameDetector;
|
||||
@ -81,7 +76,7 @@ public class FpsDebugFrameCallback implements Choreographer.FrameCallback {
|
||||
private boolean mIsRecordingFpsInfoAtEachFrame = false;
|
||||
private @Nullable TreeMap<Long, FpsInfo> mTimeToFps;
|
||||
|
||||
public FpsDebugFrameCallback(Choreographer choreographer, ReactContext reactContext) {
|
||||
public FpsDebugFrameCallback(ChoreographerCompat choreographer, ReactContext reactContext) {
|
||||
mChoreographer = choreographer;
|
||||
mReactContext = reactContext;
|
||||
mUIManagerModule = reactContext.getNativeModule(UIManagerModule.class);
|
||||
|
@ -9,20 +9,19 @@
|
||||
|
||||
package com.facebook.react.uimanager;
|
||||
|
||||
import android.view.Choreographer;
|
||||
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.modules.core.ChoreographerCompat;
|
||||
|
||||
/**
|
||||
* Abstract base for a Choreographer FrameCallback that should have any RuntimeExceptions it throws
|
||||
* handled by the {@link com.facebook.react.bridge.NativeModuleCallExceptionHandler} registered if
|
||||
* the app is in dev mode.
|
||||
*/
|
||||
public abstract class GuardedChoreographerFrameCallback implements Choreographer.FrameCallback {
|
||||
public abstract class GuardedFrameCallback extends ChoreographerCompat.FrameCallback {
|
||||
|
||||
private final ReactContext mReactContext;
|
||||
|
||||
protected GuardedChoreographerFrameCallback(ReactContext reactContext) {
|
||||
protected GuardedFrameCallback(ReactContext reactContext) {
|
||||
mReactContext = reactContext;
|
||||
}
|
||||
|
@ -722,8 +722,7 @@ public class UIViewOperationQueue {
|
||||
final int reactTag,
|
||||
final Callback callback) {
|
||||
mOperations.add(
|
||||
new MeasureInWindowOperation(reactTag, callback)
|
||||
);
|
||||
new MeasureInWindowOperation(reactTag, callback));
|
||||
}
|
||||
|
||||
public void enqueueFindTargetForTouch(
|
||||
@ -862,7 +861,7 @@ public class UIViewOperationQueue {
|
||||
* Using a Choreographer callback (which runs immediately before traversals), we guarantee we run
|
||||
* before the next traversal.
|
||||
*/
|
||||
private class DispatchUIFrameCallback extends GuardedChoreographerFrameCallback {
|
||||
private class DispatchUIFrameCallback extends GuardedFrameCallback {
|
||||
|
||||
private static final int MIN_TIME_LEFT_IN_FRAME_TO_SCHEDULE_MORE_WORK_MS = 8;
|
||||
private static final int FRAME_TIME_MS = 16;
|
||||
|
@ -17,13 +17,13 @@ import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
|
||||
import android.util.LongSparseArray;
|
||||
import android.view.Choreographer;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.LifecycleEventListener;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
import com.facebook.react.modules.core.ChoreographerCompat;
|
||||
import com.facebook.react.modules.core.ReactChoreographer;
|
||||
import com.facebook.systrace.Systrace;
|
||||
|
||||
@ -251,7 +251,7 @@ public class EventDispatcher implements LifecycleEventListener {
|
||||
(((long) coalescingKey) & 0xffff) << 48;
|
||||
}
|
||||
|
||||
private class ScheduleDispatchFrameCallback implements Choreographer.FrameCallback {
|
||||
private class ScheduleDispatchFrameCallback extends ChoreographerCompat.FrameCallback {
|
||||
private volatile boolean mIsPosted = false;
|
||||
private boolean mShouldStop = false;
|
||||
|
||||
|
@ -9,8 +9,6 @@
|
||||
|
||||
package com.facebook.react.modules.timing;
|
||||
|
||||
import android.view.Choreographer;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.ExecutorToken;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
@ -18,6 +16,7 @@ import com.facebook.react.bridge.CatalystInstance;
|
||||
import com.facebook.react.bridge.JavaOnlyArray;
|
||||
import com.facebook.react.devsupport.interfaces.DevSupportManager;
|
||||
import com.facebook.react.common.SystemClock;
|
||||
import com.facebook.react.modules.core.ChoreographerCompat;
|
||||
import com.facebook.react.modules.core.JSTimersExecution;
|
||||
import com.facebook.react.modules.core.ReactChoreographer;
|
||||
import com.facebook.react.modules.core.Timing;
|
||||
@ -39,8 +38,8 @@ import static org.mockito.Mockito.*;
|
||||
/**
|
||||
* Tests for {@link Timing}.
|
||||
*/
|
||||
// DISABLED, BROKEN https://circleci.com/gh/facebook/react-native/12068
|
||||
// t=13905097
|
||||
// DISABLED, BROKEN https://circleci.com/gh/facebook/react-native/12068
|
||||
// t=13905097
|
||||
@PrepareForTest({Arguments.class, SystemClock.class, ReactChoreographer.class})
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@ -63,12 +62,12 @@ public class TimingModuleTest {
|
||||
public void prepareModules() {
|
||||
PowerMockito.mockStatic(Arguments.class);
|
||||
when(Arguments.createArray()).thenAnswer(
|
||||
new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return new JavaOnlyArray();
|
||||
}
|
||||
});
|
||||
new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return new JavaOnlyArray();
|
||||
}
|
||||
});
|
||||
|
||||
PowerMockito.mockStatic(SystemClock.class);
|
||||
when(SystemClock.uptimeMillis()).thenReturn(mCurrentTimeNs / 1000000);
|
||||
@ -88,16 +87,16 @@ public class TimingModuleTest {
|
||||
mIdlePostFrameCallbackHandler = new PostFrameIdleCallbackHandler();
|
||||
|
||||
doAnswer(mPostFrameCallbackHandler)
|
||||
.when(mReactChoreographerMock)
|
||||
.postFrameCallback(
|
||||
eq(ReactChoreographer.CallbackType.TIMERS_EVENTS),
|
||||
any(Choreographer.FrameCallback.class));
|
||||
.when(mReactChoreographerMock)
|
||||
.postFrameCallback(
|
||||
eq(ReactChoreographer.CallbackType.TIMERS_EVENTS),
|
||||
any(ChoreographerCompat.FrameCallback.class));
|
||||
|
||||
doAnswer(mIdlePostFrameCallbackHandler)
|
||||
.when(mReactChoreographerMock)
|
||||
.postFrameCallback(
|
||||
eq(ReactChoreographer.CallbackType.IDLE_EVENT),
|
||||
any(Choreographer.FrameCallback.class));
|
||||
.when(mReactChoreographerMock)
|
||||
.postFrameCallback(
|
||||
eq(ReactChoreographer.CallbackType.IDLE_EVENT),
|
||||
any(ChoreographerCompat.FrameCallback.class));
|
||||
|
||||
mTiming = new Timing(reactContext, mock(DevSupportManager.class));
|
||||
mJSTimersMock = mock(JSTimersExecution.class);
|
||||
@ -107,7 +106,7 @@ public class TimingModuleTest {
|
||||
doAnswer(new Answer() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
((Runnable)invocation.getArguments()[0]).run();
|
||||
((Runnable) invocation.getArguments()[0]).run();
|
||||
return null;
|
||||
}
|
||||
}).when(reactContext).runOnJSQueueThread(any(Runnable.class));
|
||||
@ -116,8 +115,8 @@ public class TimingModuleTest {
|
||||
}
|
||||
|
||||
private void stepChoreographerFrame() {
|
||||
Choreographer.FrameCallback callback = mPostFrameCallbackHandler.getAndResetFrameCallback();
|
||||
Choreographer.FrameCallback idleCallback = mIdlePostFrameCallbackHandler.getAndResetFrameCallback();
|
||||
ChoreographerCompat.FrameCallback callback = mPostFrameCallbackHandler.getAndResetFrameCallback();
|
||||
ChoreographerCompat.FrameCallback idleCallback = mIdlePostFrameCallbackHandler.getAndResetFrameCallback();
|
||||
|
||||
mCurrentTimeNs += FRAME_TIME_NS;
|
||||
when(SystemClock.uptimeMillis()).thenReturn(mCurrentTimeNs / 1000000);
|
||||
@ -259,17 +258,17 @@ public class TimingModuleTest {
|
||||
|
||||
private static class PostFrameIdleCallbackHandler implements Answer<Void> {
|
||||
|
||||
private Choreographer.FrameCallback mFrameCallback;
|
||||
private ChoreographerCompat.FrameCallback mFrameCallback;
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
Object[] args = invocation.getArguments();
|
||||
mFrameCallback = (Choreographer.FrameCallback) args[1];
|
||||
mFrameCallback = (ChoreographerCompat.FrameCallback) args[1];
|
||||
return null;
|
||||
}
|
||||
|
||||
public Choreographer.FrameCallback getAndResetFrameCallback() {
|
||||
Choreographer.FrameCallback callback = mFrameCallback;
|
||||
public ChoreographerCompat.FrameCallback getAndResetFrameCallback() {
|
||||
ChoreographerCompat.FrameCallback callback = mFrameCallback;
|
||||
mFrameCallback = null;
|
||||
return callback;
|
||||
}
|
||||
@ -277,17 +276,17 @@ public class TimingModuleTest {
|
||||
|
||||
private static class PostFrameCallbackHandler implements Answer<Void> {
|
||||
|
||||
private Choreographer.FrameCallback mFrameCallback;
|
||||
private ChoreographerCompat.FrameCallback mFrameCallback;
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
Object[] args = invocation.getArguments();
|
||||
mFrameCallback = (Choreographer.FrameCallback) args[1];
|
||||
mFrameCallback = (ChoreographerCompat.FrameCallback) args[1];
|
||||
return null;
|
||||
}
|
||||
|
||||
public Choreographer.FrameCallback getAndResetFrameCallback() {
|
||||
Choreographer.FrameCallback callback = mFrameCallback;
|
||||
public ChoreographerCompat.FrameCallback getAndResetFrameCallback() {
|
||||
ChoreographerCompat.FrameCallback callback = mFrameCallback;
|
||||
mFrameCallback = null;
|
||||
return callback;
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.view.Choreographer;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
@ -29,6 +28,8 @@ import com.facebook.react.bridge.JavaOnlyArray;
|
||||
import com.facebook.react.bridge.JavaOnlyMap;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactTestHelper;
|
||||
import com.facebook.react.modules.core.ChoreographerCompat;
|
||||
import com.facebook.react.modules.core.ReactChoreographer;
|
||||
import com.facebook.react.views.text.ReactRawTextManager;
|
||||
import com.facebook.react.views.text.ReactTextShadowNode;
|
||||
import com.facebook.react.views.text.ReactTextViewManager;
|
||||
@ -70,7 +71,7 @@ public class UIManagerModuleTest {
|
||||
|
||||
private ReactApplicationContext mReactContext;
|
||||
private CatalystInstance mCatalystInstanceMock;
|
||||
private ArrayList<Choreographer.FrameCallback> mPendingChoreographerCallbacks;
|
||||
private ArrayList<ChoreographerCompat.FrameCallback> mPendingFrameCallbacks;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@ -91,17 +92,17 @@ public class UIManagerModuleTest {
|
||||
});
|
||||
PowerMockito.when(ReactChoreographer.getInstance()).thenReturn(choreographerMock);
|
||||
|
||||
mPendingChoreographerCallbacks = new ArrayList<>();
|
||||
mPendingFrameCallbacks = new ArrayList<>();
|
||||
doAnswer(new Answer() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
mPendingChoreographerCallbacks
|
||||
.add((Choreographer.FrameCallback) invocation.getArguments()[1]);
|
||||
mPendingFrameCallbacks
|
||||
.add((ChoreographerCompat.FrameCallback) invocation.getArguments()[1]);
|
||||
return null;
|
||||
}
|
||||
}).when(choreographerMock).postFrameCallback(
|
||||
any(ReactChoreographer.CallbackType.class),
|
||||
any(Choreographer.FrameCallback.class));
|
||||
any(ChoreographerCompat.FrameCallback.class));
|
||||
|
||||
mCatalystInstanceMock = ReactTestHelper.createMockCatalystInstance();
|
||||
mReactContext = new ReactApplicationContext(RuntimeEnvironment.application);
|
||||
@ -139,7 +140,7 @@ public class UIManagerModuleTest {
|
||||
JavaOnlyMap.of(ReactTextShadowNode.PROP_TEXT, "New text"));
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
assertThat(textView.getText().toString()).isEqualTo("New text");
|
||||
}
|
||||
@ -182,7 +183,7 @@ public class UIManagerModuleTest {
|
||||
null);
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
assertThat(rootView.getChildCount()).isEqualTo(1);
|
||||
|
||||
@ -213,7 +214,7 @@ public class UIManagerModuleTest {
|
||||
null);
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
assertChildrenAreExactly(
|
||||
hierarchy.nativeRootView,
|
||||
@ -240,7 +241,7 @@ public class UIManagerModuleTest {
|
||||
JavaOnlyArray.of(0, 3));
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
assertChildrenAreExactly(
|
||||
hierarchy.nativeRootView,
|
||||
@ -266,7 +267,7 @@ public class UIManagerModuleTest {
|
||||
JavaOnlyArray.of(1));
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
assertChildrenAreExactly(
|
||||
hierarchy.nativeRootView,
|
||||
@ -289,7 +290,7 @@ public class UIManagerModuleTest {
|
||||
JavaOnlyArray.of(3));
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalViewOperationException.class)
|
||||
@ -306,7 +307,7 @@ public class UIManagerModuleTest {
|
||||
JavaOnlyArray.of(3, 3));
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -335,7 +336,7 @@ public class UIManagerModuleTest {
|
||||
null);
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
assertThat(hierarchy.nativeRootView.getChildCount()).isEqualTo(5);
|
||||
assertThat(hierarchy.nativeRootView.getChildAt(0)).isEqualTo(expectedViewAt0);
|
||||
@ -363,7 +364,7 @@ public class UIManagerModuleTest {
|
||||
null);
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
assertChildrenAreExactly(
|
||||
hierarchy.nativeRootView,
|
||||
@ -392,7 +393,7 @@ public class UIManagerModuleTest {
|
||||
JavaOnlyArray.of(1));
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
assertChildrenAreExactly(
|
||||
hierarchy.nativeRootView,
|
||||
@ -424,7 +425,7 @@ public class UIManagerModuleTest {
|
||||
null);
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
View newView = hierarchy.nativeRootView.getChildAt(4);
|
||||
assertThat(newView.getLeft()).isEqualTo(10);
|
||||
@ -472,7 +473,7 @@ public class UIManagerModuleTest {
|
||||
JavaOnlyArray.of(4));
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
assertThat(hierarchy.nativeRootView.getChildCount()).isEqualTo(4);
|
||||
}
|
||||
@ -518,7 +519,7 @@ public class UIManagerModuleTest {
|
||||
ReactViewManager.REACT_CLASS,
|
||||
JavaOnlyMap.of("left", 10.0, "top", 20.0, "width", 30.0, "height", 40.0));
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
assertThat(view0.getLeft()).isGreaterThan(2);
|
||||
|
||||
// verify that the layout doesn't get updated when we update style property not affecting the
|
||||
@ -529,7 +530,7 @@ public class UIManagerModuleTest {
|
||||
ReactViewManager.REACT_CLASS,
|
||||
JavaOnlyMap.of("backgroundColor", Color.RED));
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
assertThat(view0.getLeft()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@ -565,7 +566,7 @@ public class UIManagerModuleTest {
|
||||
uiManagerModule.removeAnimation(hierarchy.rootView, 1000);
|
||||
|
||||
uiManagerModule.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
verify(callbackMock, times(1)).invoke(false);
|
||||
verify(mockAnimation).run();
|
||||
@ -591,7 +592,7 @@ public class UIManagerModuleTest {
|
||||
uiManager.replaceExistingNonRootView(hierarchy.view2, newViewTag);
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
assertThat(hierarchy.nativeRootView.getChildCount()).isEqualTo(4);
|
||||
assertThat(hierarchy.nativeRootView.getChildAt(2)).isInstanceOf(ReactViewGroup.class);
|
||||
@ -640,7 +641,7 @@ public class UIManagerModuleTest {
|
||||
addChild(uiManager, containerTag, containerTag + 3, 1);
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
assertThat(rootView.getChildCount()).isEqualTo(2);
|
||||
assertThat(((ViewGroup) rootView.getChildAt(0)).getChildCount()).isEqualTo(2);
|
||||
@ -648,7 +649,7 @@ public class UIManagerModuleTest {
|
||||
uiManager.removeSubviewsFromContainerWithID(containerTag);
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
assertThat(rootView.getChildCount()).isEqualTo(2);
|
||||
assertThat(((ViewGroup) rootView.getChildAt(0)).getChildCount()).isEqualTo(0);
|
||||
@ -693,7 +694,7 @@ public class UIManagerModuleTest {
|
||||
null);
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
return rootView;
|
||||
}
|
||||
@ -744,7 +745,7 @@ public class UIManagerModuleTest {
|
||||
addChild(uiManager, hierarchy.viewWithChildren1, hierarchy.childView1, 1);
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
|
||||
return hierarchy;
|
||||
}
|
||||
@ -803,11 +804,11 @@ public class UIManagerModuleTest {
|
||||
}
|
||||
}
|
||||
|
||||
private void executePendingChoreographerCallbacks() {
|
||||
ArrayList<Choreographer.FrameCallback> callbacks =
|
||||
new ArrayList<>(mPendingChoreographerCallbacks);
|
||||
mPendingChoreographerCallbacks.clear();
|
||||
for (Choreographer.FrameCallback frameCallback : callbacks) {
|
||||
private void executePendingFrameCallbacks() {
|
||||
ArrayList<ChoreographerCompat.FrameCallback> callbacks =
|
||||
new ArrayList<>(mPendingFrameCallbacks);
|
||||
mPendingFrameCallbacks.clear();
|
||||
for (ChoreographerCompat.FrameCallback frameCallback : callbacks) {
|
||||
frameCallback.doFrame(0);
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import android.text.TextUtils;
|
||||
import android.text.style.AbsoluteSizeSpan;
|
||||
import android.text.style.StrikethroughSpan;
|
||||
import android.text.style.UnderlineSpan;
|
||||
import android.view.Choreographer;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.react.ReactRootView;
|
||||
@ -32,7 +31,8 @@ import com.facebook.react.bridge.JavaOnlyArray;
|
||||
import com.facebook.react.bridge.JavaOnlyMap;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactTestHelper;
|
||||
import com.facebook.react.uimanager.ReactChoreographer;
|
||||
import com.facebook.react.modules.core.ChoreographerCompat;
|
||||
import com.facebook.react.modules.core.ReactChoreographer;
|
||||
import com.facebook.react.uimanager.UIImplementationProvider;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
@ -68,32 +68,32 @@ public class ReactTextTest {
|
||||
@Rule
|
||||
public PowerMockRule rule = new PowerMockRule();
|
||||
|
||||
private ArrayList<Choreographer.FrameCallback> mPendingChoreographerCallbacks;
|
||||
private ArrayList<ChoreographerCompat.FrameCallback> mPendingFrameCallbacks;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
PowerMockito.mockStatic(Arguments.class, ReactChoreographer.class);
|
||||
|
||||
ReactChoreographer choreographerMock = mock(ReactChoreographer.class);
|
||||
ReactChoreographer uiDriverMock = mock(ReactChoreographer.class);
|
||||
PowerMockito.when(Arguments.createMap()).thenAnswer(new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return new JavaOnlyMap();
|
||||
}
|
||||
});
|
||||
PowerMockito.when(ReactChoreographer.getInstance()).thenReturn(choreographerMock);
|
||||
PowerMockito.when(ReactChoreographer.getInstance()).thenReturn(uiDriverMock);
|
||||
|
||||
mPendingChoreographerCallbacks = new ArrayList<>();
|
||||
mPendingFrameCallbacks = new ArrayList<>();
|
||||
doAnswer(new Answer() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
mPendingChoreographerCallbacks
|
||||
.add((Choreographer.FrameCallback) invocation.getArguments()[1]);
|
||||
mPendingFrameCallbacks
|
||||
.add((ChoreographerCompat.FrameCallback) invocation.getArguments()[1]);
|
||||
return null;
|
||||
}
|
||||
}).when(choreographerMock).postFrameCallback(
|
||||
}).when(uiDriverMock).postFrameCallback(
|
||||
any(ReactChoreographer.CallbackType.class),
|
||||
any(Choreographer.FrameCallback.class));
|
||||
any(ChoreographerCompat.FrameCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -411,15 +411,15 @@ public class ReactTextTest {
|
||||
null);
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
executePendingFrameCallbacks();
|
||||
return rootView;
|
||||
}
|
||||
|
||||
private void executePendingChoreographerCallbacks() {
|
||||
ArrayList<Choreographer.FrameCallback> callbacks =
|
||||
new ArrayList<>(mPendingChoreographerCallbacks);
|
||||
mPendingChoreographerCallbacks.clear();
|
||||
for (Choreographer.FrameCallback frameCallback : callbacks) {
|
||||
private void executePendingFrameCallbacks() {
|
||||
ArrayList<ChoreographerCompat.FrameCallback> callbacks =
|
||||
new ArrayList<>(mPendingFrameCallbacks);
|
||||
mPendingFrameCallbacks.clear();
|
||||
for (ChoreographerCompat.FrameCallback frameCallback : callbacks) {
|
||||
frameCallback.doFrame(0);
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import android.view.Choreographer;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.facebook.react.ReactRootView;
|
||||
@ -22,8 +21,8 @@ import com.facebook.react.bridge.JavaOnlyArray;
|
||||
import com.facebook.react.bridge.JavaOnlyMap;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactTestHelper;
|
||||
import com.facebook.react.uimanager.ReactChoreographer;
|
||||
import com.facebook.react.uimanager.UIImplementation;
|
||||
import com.facebook.react.modules.core.ChoreographerCompat;
|
||||
import com.facebook.react.modules.core.ReactChoreographer;
|
||||
import com.facebook.react.uimanager.UIImplementationProvider;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
@ -58,7 +57,7 @@ public class TextInputTest {
|
||||
@Rule
|
||||
public PowerMockRule rule = new PowerMockRule();
|
||||
|
||||
private ArrayList<Choreographer.FrameCallback> mPendingChoreographerCallbacks;
|
||||
private ArrayList<ChoreographerCompat.FrameCallback> mPendingChoreographerCallbacks;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@ -78,12 +77,12 @@ public class TextInputTest {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
mPendingChoreographerCallbacks
|
||||
.add((Choreographer.FrameCallback) invocation.getArguments()[1]);
|
||||
.add((ChoreographerCompat.FrameCallback) invocation.getArguments()[1]);
|
||||
return null;
|
||||
}
|
||||
}).when(choreographerMock).postFrameCallback(
|
||||
any(ReactChoreographer.CallbackType.class),
|
||||
any(Choreographer.FrameCallback.class));
|
||||
any(ChoreographerCompat.FrameCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -169,10 +168,10 @@ public class TextInputTest {
|
||||
}
|
||||
|
||||
private void executePendingChoreographerCallbacks() {
|
||||
ArrayList<Choreographer.FrameCallback> callbacks =
|
||||
ArrayList<ChoreographerCompat.FrameCallback> callbacks =
|
||||
new ArrayList<>(mPendingChoreographerCallbacks);
|
||||
mPendingChoreographerCallbacks.clear();
|
||||
for (Choreographer.FrameCallback frameCallback : callbacks) {
|
||||
for (ChoreographerCompat.FrameCallback frameCallback : callbacks) {
|
||||
frameCallback.doFrame(0);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user