From 6876b4fb9082fe525d6edb59a834bb0e7c35ca39 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Mon, 3 Jun 2013 14:25:56 -0700 Subject: Replace HashMap with ArrayMap to remove unnecessary allocations This change also fixes a race condition. If multiple UI threads are used in a single process, RelativeLayouts could end up using the same nodes in different windows, causing mayhem and headaches. Change-Id: I9ba4a0bf05d44e1a1e7a82443d40c500c657cd7a --- core/java/android/widget/RelativeLayout.java | 127 +++++---------------------- 1 file changed, 21 insertions(+), 106 deletions(-) (limited to 'core/java/android/widget/RelativeLayout.java') diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index f940226a1a60..fd3dc037d77f 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -16,22 +16,21 @@ package android.widget; +import android.util.ArrayMap; import com.android.internal.R; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Comparator; -import java.util.HashMap; import java.util.SortedSet; import java.util.TreeSet; import android.content.Context; -import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Rect; import android.os.Build; import android.util.AttributeSet; -import android.util.Pools.SimplePool; +import android.util.Pools.SynchronizedPool; import android.util.SparseArray; import android.view.Gravity; import android.view.View; @@ -42,7 +41,6 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.widget.RemoteViews.RemoteView; import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; -import static android.util.Log.d; /** * A Layout where the positions of the children can be described in relation to each other or to the @@ -83,10 +81,6 @@ import static android.util.Log.d; */ @RemoteView public class RelativeLayout extends ViewGroup { - private static final String LOG_TAG = "RelativeLayout"; - - private static final boolean DEBUG_GRAPH = false; - public static final int TRUE = -1; /** @@ -212,8 +206,8 @@ public class RelativeLayout extends ViewGroup { private SortedSet mTopToBottomLeftToRightSet = null; private boolean mDirtyHierarchy; - private View[] mSortedHorizontalChildren = new View[0]; - private View[] mSortedVerticalChildren = new View[0]; + private View[] mSortedHorizontalChildren; + private View[] mSortedVerticalChildren; private final DependencyGraph mGraph = new DependencyGraph(); // Compatibility hack. Old versions of the platform had problems @@ -360,42 +354,26 @@ public class RelativeLayout extends ViewGroup { } private void sortChildren() { - int count = getChildCount(); - if (mSortedVerticalChildren.length != count) mSortedVerticalChildren = new View[count]; - if (mSortedHorizontalChildren.length != count) mSortedHorizontalChildren = new View[count]; + final int count = getChildCount(); + if (mSortedVerticalChildren == null || mSortedVerticalChildren.length != count) { + mSortedVerticalChildren = new View[count]; + } + + if (mSortedHorizontalChildren == null || mSortedHorizontalChildren.length != count) { + mSortedHorizontalChildren = new View[count]; + } final DependencyGraph graph = mGraph; graph.clear(); for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - graph.add(child); - } - - if (DEBUG_GRAPH) { - d(LOG_TAG, "=== Sorted vertical children"); - graph.log(getResources(), RULES_VERTICAL); - d(LOG_TAG, "=== Sorted horizontal children"); - graph.log(getResources(), RULES_HORIZONTAL); + graph.add(getChildAt(i)); } graph.getSortedViews(mSortedVerticalChildren, RULES_VERTICAL); graph.getSortedViews(mSortedHorizontalChildren, RULES_HORIZONTAL); - - if (DEBUG_GRAPH) { - d(LOG_TAG, "=== Ordered list of vertical children"); - for (View view : mSortedVerticalChildren) { - DependencyGraph.printViewId(getResources(), view); - } - d(LOG_TAG, "=== Ordered list of horizontal children"); - for (View view : mSortedHorizontalChildren) { - DependencyGraph.printViewId(getResources(), view); - } - } } - // TODO: we need to find another way to implement RelativeLayout - // This implementation cannot handle every case @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mDirtyHierarchy) { @@ -900,8 +878,6 @@ public class RelativeLayout extends ViewGroup { } else if (childParams.alignWithParent && rules[LEFT_OF] != 0) { if (myWidth >= 0) { childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin; - } else { - // FIXME uh oh... } } @@ -926,8 +902,6 @@ public class RelativeLayout extends ViewGroup { } else if (childParams.alignWithParent && rules[ALIGN_RIGHT] != 0) { if (myWidth >= 0) { childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin; - } else { - // FIXME uh oh... } } @@ -938,8 +912,6 @@ public class RelativeLayout extends ViewGroup { if (0 != rules[ALIGN_PARENT_RIGHT]) { if (myWidth >= 0) { childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin; - } else { - // FIXME uh oh... } } } @@ -958,8 +930,6 @@ public class RelativeLayout extends ViewGroup { } else if (childParams.alignWithParent && rules[ABOVE] != 0) { if (myHeight >= 0) { childParams.mBottom = myHeight - mPaddingBottom - childParams.bottomMargin; - } else { - // FIXME uh oh... } } @@ -984,8 +954,6 @@ public class RelativeLayout extends ViewGroup { } else if (childParams.alignWithParent && rules[ALIGN_BOTTOM] != 0) { if (myHeight >= 0) { childParams.mBottom = myHeight - mPaddingBottom - childParams.bottomMargin; - } else { - // FIXME uh oh... } } @@ -996,8 +964,6 @@ public class RelativeLayout extends ViewGroup { if (0 != rules[ALIGN_PARENT_BOTTOM]) { if (myHeight >= 0) { childParams.mBottom = myHeight - mPaddingBottom - childParams.bottomMargin; - } else { - // FIXME uh oh... } } @@ -1677,8 +1643,10 @@ public class RelativeLayout extends ViewGroup { sorted[index++] = view; - final HashMap dependents = node.dependents; - for (Node dependent : dependents.keySet()) { + final ArrayMap dependents = node.dependents; + final int count = dependents.size(); + for (int i = 0; i < count; i++) { + final Node dependent = dependents.keyAt(i); final SparseArray dependencies = dependent.dependencies; dependencies.remove(key); @@ -1755,61 +1723,6 @@ public class RelativeLayout extends ViewGroup { return roots; } - /** - * Prints the dependency graph for the specified rules. - * - * @param resources The context's resources to print the ids. - * @param rules The list of rules to take into account. - */ - void log(Resources resources, int... rules) { - final ArrayDeque roots = findRoots(rules); - for (Node node : roots) { - printNode(resources, node); - } - } - - static void printViewId(Resources resources, View view) { - if (view.getId() != View.NO_ID) { - d(LOG_TAG, resources.getResourceEntryName(view.getId())); - } else { - d(LOG_TAG, "NO_ID"); - } - } - - private static void appendViewId(Resources resources, Node node, StringBuilder buffer) { - if (node.view.getId() != View.NO_ID) { - buffer.append(resources.getResourceEntryName(node.view.getId())); - } else { - buffer.append("NO_ID"); - } - } - - private static void printNode(Resources resources, Node node) { - if (node.dependents.size() == 0) { - printViewId(resources, node.view); - } else { - for (Node dependent : node.dependents.keySet()) { - StringBuilder buffer = new StringBuilder(); - appendViewId(resources, node, buffer); - printdependents(resources, dependent, buffer); - } - } - } - - private static void printdependents(Resources resources, Node node, StringBuilder buffer) { - buffer.append(" -> "); - appendViewId(resources, node, buffer); - - if (node.dependents.size() == 0) { - d(LOG_TAG, buffer.toString()); - } else { - for (Node dependent : node.dependents.keySet()) { - StringBuilder subBuffer = new StringBuilder(buffer); - printdependents(resources, dependent, subBuffer); - } - } - } - /** * A node in the dependency graph. A node is a view, its list of dependencies * and its list of dependents. @@ -1826,7 +1739,8 @@ public class RelativeLayout extends ViewGroup { * The list of dependents for this node; a dependent is a node * that needs this node to be processed first. */ - final HashMap dependents = new HashMap(); + final ArrayMap dependents = + new ArrayMap(); /** * The list of dependencies for this node. @@ -1839,7 +1753,8 @@ public class RelativeLayout extends ViewGroup { // The pool is static, so all nodes instances are shared across // activities, that's why we give it a rather high limit private static final int POOL_LIMIT = 100; - private static final SimplePool sPool = new SimplePool(POOL_LIMIT); + private static final SynchronizedPool sPool = + new SynchronizedPool(POOL_LIMIT); static Node acquire(View view) { Node node = sPool.acquire(); -- cgit v1.2.3