mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
rn-android | Add abstraction layer between ReactChoreographer and android.view.Choreographer that allows substituting current implementation.
Summary: We want to have an extension point for choreographer, so we can override default behavior and have either rate-limiting, or testing or other form of manual control. For all those cases allow substitution of choreographer that ReactChoreographer would use by default with a custom one. Changelog: [Android][Added] ReactChoreographer can now use an implementation substitution instead of relying on android.view.Choreographer directly. Reviewed By: javache Differential Revision: D50827975 fbshipit-source-id: 0fd78e1f4f96ffd832e5d8cdc6c805f9a9e272cf
This commit is contained in:
committed by
Facebook GitHub Bot
parent
ae85be3e92
commit
751f7e97ba
+2
-1
@@ -22,6 +22,7 @@ import com.facebook.react.bridge.SoftAssertions;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.common.futures.SimpleSettableFuture;
|
||||
import com.facebook.react.devsupport.interfaces.DevSupportManager;
|
||||
import com.facebook.react.internal.AndroidChoreographerProvider;
|
||||
import com.facebook.react.modules.core.ReactChoreographer;
|
||||
import com.facebook.react.modules.core.TimingModule;
|
||||
import com.facebook.react.testing.idledetection.ReactBridgeIdleSignaler;
|
||||
@@ -134,7 +135,7 @@ public abstract class ReactIntegrationTestCase extends AndroidTestCase {
|
||||
new SimpleSettableFuture<TimingModule>();
|
||||
UiThreadUtil.runOnUiThread(
|
||||
() -> {
|
||||
ReactChoreographer.initialize();
|
||||
ReactChoreographer.initialize(AndroidChoreographerProvider.getInstance());
|
||||
TimingModule timingModule =
|
||||
new TimingModule(getContext(), Mockito.mock(DevSupportManager.class));
|
||||
simpleSettableFuture.set(timingModule);
|
||||
|
||||
+2
-1
@@ -29,6 +29,7 @@ import com.facebook.react.bridge.JavaScriptExecutor;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.queue.ReactQueueConfigurationSpec;
|
||||
import com.facebook.react.internal.AndroidChoreographerProvider;
|
||||
import com.facebook.react.modules.core.ReactChoreographer;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import java.util.Arrays;
|
||||
@@ -149,7 +150,7 @@ public class ReactTestHelper {
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ReactChoreographer.initialize();
|
||||
ReactChoreographer.initialize(AndroidChoreographerProvider.getInstance());
|
||||
instance.initialize();
|
||||
}
|
||||
});
|
||||
|
||||
+2
-1
@@ -87,6 +87,7 @@ import com.facebook.react.devsupport.interfaces.DevLoadingViewManager;
|
||||
import com.facebook.react.devsupport.interfaces.DevSupportManager;
|
||||
import com.facebook.react.devsupport.interfaces.PackagerStatusCallback;
|
||||
import com.facebook.react.devsupport.interfaces.RedBoxHandler;
|
||||
import com.facebook.react.internal.AndroidChoreographerProvider;
|
||||
import com.facebook.react.internal.turbomodule.core.TurboModuleManager;
|
||||
import com.facebook.react.internal.turbomodule.core.TurboModuleManagerDelegate;
|
||||
import com.facebook.react.modules.appearance.AppearanceModule;
|
||||
@@ -293,7 +294,7 @@ public class ReactInstanceManager {
|
||||
mJSIModulePackage = jsiModulePackage;
|
||||
|
||||
// Instantiate ReactChoreographer in UI thread.
|
||||
ReactChoreographer.initialize();
|
||||
ReactChoreographer.initialize(AndroidChoreographerProvider.getInstance());
|
||||
if (mUseDeveloperSupport) {
|
||||
mDevSupportManager.startInspector();
|
||||
}
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.internal;
|
||||
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
|
||||
/** An implementation of ChoreographerProvider that directly uses android.view.Choreographer. */
|
||||
public final class AndroidChoreographerProvider implements ChoreographerProvider {
|
||||
|
||||
public static final class AndroidChoreographer implements ChoreographerProvider.Choreographer {
|
||||
private final android.view.Choreographer sInstance = android.view.Choreographer.getInstance();
|
||||
|
||||
public void postFrameCallback(android.view.Choreographer.FrameCallback callback) {
|
||||
sInstance.postFrameCallback(callback);
|
||||
}
|
||||
|
||||
public void removeFrameCallback(android.view.Choreographer.FrameCallback callback) {
|
||||
sInstance.removeFrameCallback(callback);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Holder {
|
||||
private static final AndroidChoreographerProvider INSTANCE = new AndroidChoreographerProvider();
|
||||
}
|
||||
|
||||
public static AndroidChoreographerProvider getInstance() {
|
||||
return Holder.INSTANCE;
|
||||
}
|
||||
|
||||
public Choreographer getChoreographer() {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
return new AndroidChoreographer();
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.internal;
|
||||
|
||||
public interface ChoreographerProvider {
|
||||
/**
|
||||
* The interface to a android.view.Choreographer-like object, that can either use the
|
||||
* android.view.Choreographer or a mock one for testing purposes, or override built-in
|
||||
* android.view.Choreographer's behaviors.
|
||||
*/
|
||||
interface Choreographer {
|
||||
|
||||
/** Posts a frame callback to run on the next frame. */
|
||||
void postFrameCallback(android.view.Choreographer.FrameCallback callback);
|
||||
/** Removes a previously posted frame callback. */
|
||||
void removeFrameCallback(android.view.Choreographer.FrameCallback callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of Choreographer.
|
||||
*
|
||||
* @return An instance of Choreographer.
|
||||
*/
|
||||
Choreographer getChoreographer();
|
||||
}
|
||||
+6
-6
@@ -13,6 +13,7 @@ import com.facebook.common.logging.FLog;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.internal.ChoreographerProvider;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
/**
|
||||
@@ -55,9 +56,9 @@ public final class ReactChoreographer {
|
||||
|
||||
private static ReactChoreographer sInstance;
|
||||
|
||||
public static void initialize() {
|
||||
public static void initialize(ChoreographerProvider choreographerProvider) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new ReactChoreographer();
|
||||
sInstance = new ReactChoreographer(choreographerProvider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,8 +67,7 @@ public final class ReactChoreographer {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
// This needs to be volatile due to double checked locking issue - https://fburl.com/z409owpf
|
||||
private @Nullable volatile Choreographer mChoreographer;
|
||||
private @Nullable ChoreographerProvider.Choreographer mChoreographer;
|
||||
|
||||
private final ArrayDeque<Choreographer.FrameCallback>[] mCallbackQueues;
|
||||
|
||||
@@ -101,7 +101,7 @@ public final class ReactChoreographer {
|
||||
private int mTotalCallbacks = 0;
|
||||
private boolean mHasPostedCallback = false;
|
||||
|
||||
private ReactChoreographer() {
|
||||
private ReactChoreographer(ChoreographerProvider choreographerProvider) {
|
||||
mCallbackQueues = new ArrayDeque[CallbackType.values().length];
|
||||
for (int i = 0; i < mCallbackQueues.length; i++) {
|
||||
mCallbackQueues[i] = new ArrayDeque<>();
|
||||
@@ -109,7 +109,7 @@ public final class ReactChoreographer {
|
||||
|
||||
UiThreadUtil.runOnUiThread(
|
||||
() -> {
|
||||
mChoreographer = Choreographer.getInstance();
|
||||
mChoreographer = choreographerProvider.getChoreographer();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -44,6 +44,7 @@ import com.facebook.react.fabric.FabricUIManager;
|
||||
import com.facebook.react.fabric.ReactNativeConfig;
|
||||
import com.facebook.react.fabric.events.EventBeatManager;
|
||||
import com.facebook.react.interfaces.exceptionmanager.ReactJsExceptionHandler;
|
||||
import com.facebook.react.internal.AndroidChoreographerProvider;
|
||||
import com.facebook.react.internal.turbomodule.core.CallInvokerHolderImpl;
|
||||
import com.facebook.react.internal.turbomodule.core.NativeMethodCallInvokerHolderImpl;
|
||||
import com.facebook.react.internal.turbomodule.core.TurboModuleManager;
|
||||
@@ -137,7 +138,7 @@ final class ReactInstance {
|
||||
MessageQueueThread nativeModulesMessageQueueThread =
|
||||
mQueueConfiguration.getNativeModulesQueueThread();
|
||||
|
||||
ReactChoreographer.initialize();
|
||||
ReactChoreographer.initialize(AndroidChoreographerProvider.getInstance());
|
||||
if (useDevSupport) {
|
||||
devSupportManager.startInspector();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user