Improve logic to report mounted surfaces (#43337)

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

Changelog: [internal]

Mount instructions and listeners are only called from the UI thread, so there's no need to have synchronization mechanisms for concurrency.

We're also scheduling mount hooks notifications once, but subsequent calls are ignored instead of accumulated to be notified together. This also changes that to collect all the surface IDs in the array that is read on notification.

Reviewed By: sammy-SC

Differential Revision: D54547194

fbshipit-source-id: a861e3b0113914aae5325c1486bcf8acd50eef79
This commit is contained in:
Rubén Norte
2024-03-06 12:41:49 -08:00
committed by Facebook GitHub Bot
parent 028615180b
commit a66f4450e5
@@ -91,7 +91,6 @@ import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* We instruct ProGuard not to strip out any fields or methods, because many of these methods are
@@ -173,7 +172,8 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
@NonNull
private final CopyOnWriteArrayList<UIManagerListener> mListeners = new CopyOnWriteArrayList<>();
@NonNull private final AtomicBoolean mMountNotificationScheduled = new AtomicBoolean(false);
private boolean mMountNotificationScheduled = false;
private final List<Integer> mMountedSurfaceIds = new ArrayList<>();
@ThreadConfined(UI)
@NonNull
@@ -1203,6 +1203,8 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
}
private class MountItemDispatchListener implements MountItemDispatcher.ItemDispatchListener {
@UiThread
@ThreadConfined(UI)
@Override
public void willMountItems(@Nullable List<MountItem> mountItems) {
for (UIManagerListener listener : mListeners) {
@@ -1210,18 +1212,26 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
}
}
@UiThread
@ThreadConfined(UI)
@Override
public void didMountItems(@Nullable List<MountItem> mountItems) {
for (UIManagerListener listener : mListeners) {
listener.didMountItems(FabricUIManager.this);
}
if (!ReactFeatureFlags.enableMountHooks) {
if (!ReactFeatureFlags.enableMountHooks || mountItems == null || mountItems.isEmpty()) {
return;
}
boolean mountNotificationScheduled = mMountNotificationScheduled.getAndSet(true);
if (!mountNotificationScheduled) {
// Collect surface IDs for all the mount items
for (MountItem mountItem : mountItems) {
if (mountItem != null && !mMountedSurfaceIds.contains(mountItem.getSurfaceId())) {
mMountedSurfaceIds.add(mountItem.getSurfaceId());
}
}
if (!mMountNotificationScheduled && !mMountedSurfaceIds.isEmpty()) {
// Notify mount when the effects are visible and prevent mount hooks to
// delay paint.
UiThreadUtil.getUiThreadHandler()
@@ -1229,28 +1239,19 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
new Runnable() {
@Override
public void run() {
mMountNotificationScheduled.set(false);
if (mDestroyed) {
return;
}
mMountNotificationScheduled = false;
final @Nullable Binding binding = mBinding;
if (mountItems == null || binding == null) {
if (binding == null || mDestroyed) {
mMountedSurfaceIds.clear();
return;
}
// Collect surface IDs for all the mount items
List<Integer> surfaceIds = new ArrayList<>();
for (MountItem mountItem : mountItems) {
if (mountItem != null && !surfaceIds.contains(mountItem.getSurfaceId())) {
surfaceIds.add(mountItem.getSurfaceId());
}
}
for (int surfaceId : surfaceIds) {
for (int surfaceId : mMountedSurfaceIds) {
binding.reportMount(surfaceId);
}
mMountedSurfaceIds.clear();
}
});
}