mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
only schedule frame callback when there are mount items in FabricUIManager
Summary: changelog: [internal] It is redundant to schedule frame callback if there is no work to do. Let's remove it. Reviewed By: javache Differential Revision: D50494928 fbshipit-source-id: fce7d9a84eb2486dc01d4bff98540c128b91969d
This commit is contained in:
1 parent
4655f2063d
commit
885a4ae09d
3 files changed
+74
-14
No files matched your search
+6
@@ -182,4 +182,10 @@ public class ReactFeatureFlags {
|
||||
* longer work as they won't subscribe to ReactChoregrapher for updates.
|
||||
*/
|
||||
public static boolean enableFabricRendererExclusively = false;
|
||||
|
||||
/*
|
||||
* When enabled, uses of ReactChoreographer (e.g. FabricUIManager) will only post callback
|
||||
* when there is work to do.
|
||||
*/
|
||||
public static boolean enableOnDemandReactChoreographer = false;
|
||||
}
|
||||
+64
-14
@@ -52,6 +52,7 @@ import com.facebook.react.bridge.UIManager;
|
||||
import com.facebook.react.bridge.UIManagerListener;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.common.LifecycleState;
|
||||
import com.facebook.react.common.build.ReactBuildConfig;
|
||||
import com.facebook.react.common.mapbuffer.ReadableMapBuffer;
|
||||
import com.facebook.react.config.ReactFeatureFlags;
|
||||
@@ -188,6 +189,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
private volatile boolean mDestroyed = false;
|
||||
|
||||
private boolean mDriveCxxAnimations = false;
|
||||
private final AtomicBoolean mIsFrameCallbackScheduled = new AtomicBoolean(false);
|
||||
|
||||
private long mDispatchViewUpdatesTime = 0l;
|
||||
private long mCommitStartTime = 0l;
|
||||
@@ -693,7 +695,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
// If the reactTag exists, we assume that it might at the end of the next
|
||||
// batch of MountItems. Otherwise, we try to execute immediately.
|
||||
if (!mMountingManager.getViewExists(reactTag)) {
|
||||
mMountItemDispatcher.addMountItem(synchronousMountItem);
|
||||
addMountItem(synchronousMountItem);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -726,7 +728,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
@Nullable Object eventEmitterWrapper,
|
||||
boolean isLayoutable) {
|
||||
|
||||
mMountItemDispatcher.addPreAllocateMountItem(
|
||||
addPreAllocateMountItem(
|
||||
MountItemFactory.createPreAllocateViewMountItem(
|
||||
rootTag,
|
||||
reactTag,
|
||||
@@ -799,6 +801,8 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
};
|
||||
if (UiThreadUtil.isOnUiThread()) {
|
||||
runnable.run();
|
||||
} else {
|
||||
postChoreographerCallbackIfNecessary();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -959,10 +963,50 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
}
|
||||
}
|
||||
|
||||
private void addPreAllocateMountItem(final MountItem mountItem) {
|
||||
mMountItemDispatcher.addPreAllocateMountItem(mountItem);
|
||||
postChoreographerCallbackIfNecessary();
|
||||
}
|
||||
|
||||
private void addMountItem(final MountItem mountItem) {
|
||||
mMountItemDispatcher.addMountItem(mountItem);
|
||||
postChoreographerCallbackIfNecessary();
|
||||
}
|
||||
|
||||
private void addViewCommandMountItem(final DispatchCommandMountItem mountItem) {
|
||||
mMountItemDispatcher.addViewCommandMountItem(mountItem);
|
||||
postChoreographerCallbackIfNecessary();
|
||||
}
|
||||
|
||||
private void postChoreographerCallbackIfNecessary() {
|
||||
if (ReactFeatureFlags.enableOnDemandReactChoreographer == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mIsFrameCallbackScheduled.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isWorkPending = mMountItemDispatcher.hasMountItems() || mDriveCxxAnimations;
|
||||
boolean isAppActive = mReactApplicationContext.getLifecycleState() == LifecycleState.RESUMED;
|
||||
|
||||
if (isWorkPending && isAppActive) {
|
||||
// It is important to only schedule one frame callback at a time.
|
||||
// Otherwise, with LayoutAnimations, deadlock may occur.
|
||||
mIsFrameCallbackScheduled.set(true);
|
||||
ReactChoreographer.getInstance()
|
||||
.postFrameCallback(ReactChoreographer.CallbackType.DISPATCH_UI, mDispatchUIFrameCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHostResume() {
|
||||
ReactChoreographer.getInstance()
|
||||
.postFrameCallback(ReactChoreographer.CallbackType.DISPATCH_UI, mDispatchUIFrameCallback);
|
||||
if (ReactFeatureFlags.enableOnDemandReactChoreographer) {
|
||||
postChoreographerCallbackIfNecessary();
|
||||
} else {
|
||||
ReactChoreographer.getInstance()
|
||||
.postFrameCallback(ReactChoreographer.CallbackType.DISPATCH_UI, mDispatchUIFrameCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1009,7 +1053,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
final int reactTag,
|
||||
final int commandId,
|
||||
@Nullable final ReadableArray commandArgs) {
|
||||
mMountItemDispatcher.addViewCommandMountItem(
|
||||
addViewCommandMountItem(
|
||||
MountItemFactory.createDispatchCommandMountItem(
|
||||
surfaceId, reactTag, commandId, commandArgs));
|
||||
}
|
||||
@@ -1025,10 +1069,10 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
// For Fabric Interop, we check if the commandId is an integer. If it is, we use the integer
|
||||
// overload of dispatchCommand. Otherwise, we use the string overload.
|
||||
// and the events won't be correctly dispatched.
|
||||
mMountItemDispatcher.addViewCommandMountItem(
|
||||
addViewCommandMountItem(
|
||||
createDispatchCommandMountItemForInterop(surfaceId, reactTag, commandId, commandArgs));
|
||||
} else {
|
||||
mMountItemDispatcher.addViewCommandMountItem(
|
||||
addViewCommandMountItem(
|
||||
MountItemFactory.createDispatchCommandMountItem(
|
||||
surfaceId, reactTag, commandId, commandArgs));
|
||||
}
|
||||
@@ -1040,7 +1084,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
public void sendAccessibilityEvent(int reactTag, int eventType) {
|
||||
// Can be called from native, not just JS - we need to migrate the native callsites
|
||||
// before removing this entirely.
|
||||
mMountItemDispatcher.addMountItem(
|
||||
addMountItem(
|
||||
MountItemFactory.createSendAccessibilityEventMountItem(View.NO_ID, reactTag, eventType));
|
||||
}
|
||||
|
||||
@@ -1060,7 +1104,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
throw new IllegalArgumentException(
|
||||
"sendAccessibilityEventFromJS: invalid eventType " + eventTypeJS);
|
||||
}
|
||||
mMountItemDispatcher.addMountItem(
|
||||
addMountItem(
|
||||
MountItemFactory.createSendAccessibilityEventMountItem(surfaceId, reactTag, eventType));
|
||||
}
|
||||
|
||||
@@ -1076,7 +1120,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
final int reactTag,
|
||||
final int initialReactTag,
|
||||
final boolean blockNativeResponder) {
|
||||
mMountItemDispatcher.addMountItem(
|
||||
addMountItem(
|
||||
new MountItem() {
|
||||
@Override
|
||||
public void execute(@NonNull MountingManager mountingManager) {
|
||||
@@ -1110,7 +1154,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
* the touch events are going to be handled by JS.
|
||||
*/
|
||||
public void clearJSResponder() {
|
||||
mMountItemDispatcher.addMountItem(
|
||||
addMountItem(
|
||||
new MountItem() {
|
||||
@Override
|
||||
public void execute(@NonNull MountingManager mountingManager) {
|
||||
@@ -1151,6 +1195,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
@AnyThread
|
||||
public void onAnimationStarted() {
|
||||
mDriveCxxAnimations = true;
|
||||
postChoreographerCallbackIfNecessary();
|
||||
}
|
||||
|
||||
// Called from Binding.cpp
|
||||
@@ -1266,6 +1311,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
@UiThread
|
||||
@ThreadConfined(UI)
|
||||
public void doFrameGuarded(long frameTimeNanos) {
|
||||
mIsFrameCallbackScheduled.set(false);
|
||||
if (!mIsMountingEnabled || mDestroyed) {
|
||||
FLog.w(TAG, "Not flushing pending UI operations because of previously thrown Exception");
|
||||
return;
|
||||
@@ -1292,9 +1338,13 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
stop();
|
||||
throw ex;
|
||||
} finally {
|
||||
ReactChoreographer.getInstance()
|
||||
.postFrameCallback(
|
||||
ReactChoreographer.CallbackType.DISPATCH_UI, mDispatchUIFrameCallback);
|
||||
if (ReactFeatureFlags.enableOnDemandReactChoreographer == false) {
|
||||
ReactChoreographer.getInstance()
|
||||
.postFrameCallback(
|
||||
ReactChoreographer.CallbackType.DISPATCH_UI, mDispatchUIFrameCallback);
|
||||
} else {
|
||||
postChoreographerCallbackIfNecessary();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -304,6 +304,10 @@ public class MountItemDispatcher {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasMountItems() {
|
||||
return !mPreMountItems.isEmpty() || !mMountItems.isEmpty() || !mViewCommandMountItems.isEmpty();
|
||||
}
|
||||
|
||||
/*
|
||||
* Executes pre mount items. Pre mount items are operations that can be executed before the mount items come. For example view preallocation.
|
||||
* This is a performance optimisation to do as much work ahead of time as possible.
|
||||
|
||||
Reference in new issue
Block a user