Coordinate Synchronous Events with Choreographer (#44491)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44491

Changelog: [internal]

Ensure only one scroll event is fired per frame by tracking the events in FabricUIManager

Reviewed By: sammy-SC

Differential Revision: D57018741

fbshipit-source-id: c1ad59f934e359edfeb8f3e084106eebd467a0b1
This commit is contained in:
Thomas Nardone
2024-05-08 14:32:24 -07:00
committed by Facebook GitHub Bot
parent 52ca6f6569
commit 2ac8dc1e78
2 changed files with 31 additions and 1 deletions
@@ -89,9 +89,11 @@ import com.facebook.react.uimanager.events.SynchronousEventReceiver;
import com.facebook.react.views.text.TextLayoutManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -183,6 +185,9 @@ public class FabricUIManager
@NonNull
private final DispatchUIFrameCallback mDispatchUIFrameCallback;
/** Set of events sent synchronously during the current frame render. Cleared after each frame. */
private final Set<SynchronousEvent> mSynchronousEvents = new HashSet<>();
/**
* This is used to keep track of whether or not the FabricUIManager has been destroyed. Once the
* Catalyst instance is being destroyed, we should cease all operation here.
@@ -995,7 +1000,12 @@ public class FabricUIManager
}
if (experimental_isSynchronous) {
eventEmitter.dispatchEventSynchronously(eventName, params);
// add() returns true only if there are no equivalent events already in the set
boolean firstEventForFrame =
mSynchronousEvents.add(new SynchronousEvent(surfaceId, reactTag, eventName));
if (firstEventForFrame) {
eventEmitter.dispatchEventSynchronously(eventName, params);
}
} else {
if (canCoalesceEvent) {
eventEmitter.dispatchUnique(eventName, params);
@@ -1351,6 +1361,8 @@ public class FabricUIManager
.postFrameCallback(
ReactChoreographer.CallbackType.DISPATCH_UI, mDispatchUIFrameCallback);
}
mSynchronousEvents.clear();
}
}
}
@@ -0,0 +1,18 @@
/*
* 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.fabric
/**
* Represents the identifying criteria of a synchronous event that was sent directly on the main
* thread. Used to determine if subsequent events are duplicates and should not be emitted.
*/
internal data class SynchronousEvent(
val surfaceId: Int,
val viewTag: Int,
val eventName: String,
)