From b673e352fb0ea44b545edf5a7e8c1b422180838a Mon Sep 17 00:00:00 2001 From: David Alves Date: Fri, 25 Jun 2021 13:22:41 -0700 Subject: [PATCH] Use weak hash map for react scroll view helper Summary: This prevents us from leaking things via this static field. Changelog: [Android][Changed] Native ScrollView listeners list maintains weak references to listeners to avoid memory leaks Reviewed By: JoshuaGross Differential Revision: D29317937 fbshipit-source-id: 4daeb8b5533cccaebcb03acf3d595dfa58de7883 --- .../views/scroll/ReactScrollViewHelper.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java index b46874aaf14..a9c83ee5069 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java @@ -14,8 +14,9 @@ import android.widget.OverScroller; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReactContext; import com.facebook.react.uimanager.UIManagerHelper; -import java.util.ArrayList; -import java.util.List; +import java.util.Collections; +import java.util.Set; +import java.util.WeakHashMap; /** Helper class that deals with emitting Scroll Events. */ public class ReactScrollViewHelper { @@ -33,7 +34,8 @@ public class ReactScrollViewHelper { } // Support global native listeners for scroll events - private static List sScrollListeners = new ArrayList<>(); + private static Set sScrollListeners = + Collections.newSetFromMap(new WeakHashMap()); // If all else fails, this is the hardcoded value in OverScroller.java, in AOSP. // The default is defined here (as of this diff): @@ -156,6 +158,19 @@ public class ReactScrollViewHelper { } } + /** + * Adds a scroll listener. + * + *

Note that you must keep a reference to this scroll listener because this class only keeps a + * weak reference to it (to prevent memory leaks). This means that code like + * addScrollListener(new ScrollListener() {...}) won't work, you need to do this instead: + * + * mScrollListener = new ScrollListener() {...}; + * ReactScrollViewHelper.addScrollListener(mScrollListener); + * instead. + * + * @param listener + */ public static void addScrollListener(ScrollListener listener) { sScrollListeners.add(listener); }