From a6028919462b41ed5ebf24011e80f18eb0bc2143 Mon Sep 17 00:00:00 2001 From: Seth Kirby Date: Mon, 15 Aug 2016 20:39:50 -0700 Subject: [PATCH] Use SparseArray for detached views. Summary: This is minor, but for our use case a SparseArray is going to be faster as long as we have less than 10,000 clipped subviews, and will also use much less memory. Faster because of the boxing, unboxing and hash caching; less memory as it is two arrays instead of the object overhead of the HashMap. Reviewed By: ahmedre Differential Revision: D3704326 --- .../react/flat/ClippingDrawCommandManager.java | 10 +++++----- .../com/facebook/react/flat/DrawCommandManager.java | 3 ++- .../react/flat/FlatNativeViewHierarchyManager.java | 6 ++++-- .../java/com/facebook/react/flat/FlatViewGroup.java | 5 +++-- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/ClippingDrawCommandManager.java b/ReactAndroid/src/main/java/com/facebook/react/flat/ClippingDrawCommandManager.java index b09b05166..bbba7272c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/ClippingDrawCommandManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/ClippingDrawCommandManager.java @@ -163,7 +163,7 @@ import com.facebook.react.views.view.ReactClippingViewGroupHelper; // less in our case because of the large constant overhead and auto boxing of the map. private SparseIntArray mDrawViewIndexMap = StateBuilder.EMPTY_SPARSE_INT; // Map of views that are currently clipped. - private final Map mClippedSubviews = new HashMap<>(); + private final SparseArray mClippedSubviews = new SparseArray<>(); protected final Rect mClippingRect = new Rect(); @@ -297,11 +297,11 @@ import com.facebook.react.views.view.ReactClippingViewGroupHelper; } private boolean isClipped(int id) { - return mClippedSubviews.containsKey(id); + return mClippedSubviews.get(id) != null; } private boolean isNotClipped(int id) { - return !mClippedSubviews.containsKey(id); + return mClippedSubviews.get(id) == null; } @Override @@ -510,8 +510,8 @@ import com.facebook.react.views.view.ReactClippingViewGroupHelper; } @Override - public Collection getDetachedViews() { - return mClippedSubviews.values(); + public SparseArray getDetachedViews() { + return mClippedSubviews; } /** diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawCommandManager.java b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawCommandManager.java index f87e82596..18c0a1bb8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawCommandManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawCommandManager.java @@ -15,6 +15,7 @@ import java.util.Collection; import android.graphics.Canvas; import android.graphics.Rect; +import android.util.SparseArray; import android.util.SparseIntArray; import android.view.View; import android.view.ViewParent; @@ -78,7 +79,7 @@ import android.view.ViewParent; * * @return A collection of the currently detached views. */ - abstract Collection getDetachedViews(); + abstract SparseArray getDetachedViews(); /** * Draw the relevant items. This should do as little work as possible. diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatNativeViewHierarchyManager.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatNativeViewHierarchyManager.java index 042be375a..a8d440118 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatNativeViewHierarchyManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatNativeViewHierarchyManager.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import android.util.SparseArray; import android.util.SparseIntArray; import android.view.View; import android.view.View.MeasureSpec; @@ -208,8 +209,9 @@ import com.facebook.react.uimanager.ViewManagerRegistry; if (view instanceof FlatViewGroup) { FlatViewGroup flatViewGroup = (FlatViewGroup) view; if (flatViewGroup.getRemoveClippedSubviews()) { - Collection detachedViews = flatViewGroup.getDetachedViews(); - for (View detachedChild : detachedViews) { + SparseArray detachedViews = flatViewGroup.getDetachedViews(); + for (int i = 0, size = detachedViews.size(); i < size; i++) { + View detachedChild = detachedViews.valueAt(i); // we can do super here because removeClippedSubviews is currently not recursive. if/when // we become recursive one day, this should call vanilla dropView to be recursive as well. super.dropView(detachedChild); diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java index 1675ef147..53c01d20e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java @@ -22,6 +22,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.util.SparseArray; import android.util.SparseIntArray; import android.view.MotionEvent; import android.view.View; @@ -166,7 +167,7 @@ import com.facebook.react.views.view.ReactClippingViewGroup; private long mLastTouchDownTime; private @Nullable OnInterceptTouchEventListener mOnInterceptTouchEventListener; - private static final ArrayList EMPTY_DETACHED_VIEWS = new ArrayList<>(0); + private static final SparseArray EMPTY_DETACHED_VIEWS = new SparseArray<>(0); // Provides clipping, drawing and node region finding logic if subview clipping is enabled. private @Nullable DrawCommandManager mDrawCommandManager; @@ -778,7 +779,7 @@ import com.facebook.react.views.view.ReactClippingViewGroup; * * @return A Collection of Views to clean up. */ - Collection getDetachedViews() { + /* package */ SparseArray getDetachedViews() { if (mDrawCommandManager == null) { return EMPTY_DETACHED_VIEWS; }