From 85aefd944dae3e330fa2ce63e806786ef47ffdd1 Mon Sep 17 00:00:00 2001 From: Peter Abbondanzo Date: Thu, 11 Sep 2025 10:14:06 -0700 Subject: [PATCH] Add API 26 check to ReactScrollViewHelper (#53688) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53688 Support for the `removeIf` method was [added to CopyOnWriteArrayList with AOSP in API 26](https://android-review.googlesource.com/c/platform/libcore/+/304056). On devices with API 24 and 25, invocations of either `ReactScrollViewHelper#removeScrollListener` or `ReactScrollViewHelper#removeLayoutChangeListener` would cause a crash. Rather than bump the required API version and lock out apps targeting API 24/25, this adds a separate code path to bulk remove items from the array list. Changelog: [Internal] Differential Revision: D82039300 --- .../views/scroll/ReactScrollViewHelper.kt | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt index ea5b3a3890e2..4621ccaf8aee 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt @@ -245,7 +245,15 @@ public object ReactScrollViewHelper { @RequiresApi(Build.VERSION_CODES.N) @JvmStatic public fun removeScrollListener(listener: ScrollListener) { - scrollListeners.removeIf { it.get() == null || it.get() == listener } + // Avoid using removeIf, only available in API 26+ + val toRemove = ArrayList>() + for (ref in scrollListeners) { + val target = ref.get() + if (target == null || target == listener) { + toRemove.add(ref) + } + } + scrollListeners.removeAll(toRemove) } @JvmStatic @@ -256,7 +264,15 @@ public object ReactScrollViewHelper { @RequiresApi(Build.VERSION_CODES.N) @JvmStatic public fun removeLayoutChangeListener(listener: LayoutChangeListener) { - layoutChangeListeners.removeIf { it.get() == null || it.get() == listener } + // Avoid using removeIf, only available in API 26+ + val toRemove = ArrayList>() + for (ref in layoutChangeListeners) { + val target = ref.get() + if (target == null || target == listener) { + toRemove.add(ref) + } + } + layoutChangeListeners.removeAll(toRemove) } /**