Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7db82acd authored by Adam Powell's avatar Adam Powell
Browse files

Fix leaky view tags

The implementation of the method View#setTag(int, Object) stored tag
objects as entries in a static WeakHashMap associated with the View as
a key. This was problematic for any tag object that stored a hard
reference back to the View the tag was placed on, as it would cause
the WeakReference key to never be collected and the entry to persist
forever.

This was particularly nasty if an app used a keyed tag to store a
ViewHolder object referencing child views for use in the Adapter
implementaion for an AdapterView, since child views will always have
hard references leading back to the parent.

Change-Id: Ia17840a301ba0e0c928861405388fb2f625dac2c
parent e94d950d
Loading
Loading
Loading
Loading
+8 −33
Original line number Diff line number Diff line
@@ -81,7 +81,6 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -1497,12 +1496,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
    /**
     * Map used to store views' tags.
     */
    private static WeakHashMap<View, SparseArray<Object>> sTags;
    /**
     * Lock used to access sTags.
     */
    private static final Object sTagsLock = new Object();
    private SparseArray<Object> mKeyedTags;
    /**
     * The next available accessiiblity id.
@@ -12236,14 +12230,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
     * @see #getTag()
     */
    public Object getTag(int key) {
        SparseArray<Object> tags = null;
        synchronized (sTagsLock) {
            if (sTags != null) {
                tags = sTags.get(this);
            }
        }
        if (tags != null) return tags.get(key);
        if (mKeyedTags != null) return mKeyedTags.get(key);
        return null;
    }
@@ -12276,7 +12263,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
                    + "resource id.");
        }
        setTagInternal(this, key, tag);
        setKeyedTag(this, key, tag);
    }
    /**
@@ -12291,27 +12278,15 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
                    + "resource id.");
        }
        setTagInternal(this, key, tag);
        setKeyedTag(this, key, tag);
    }
    private static void setTagInternal(View view, int key, Object tag) {
        SparseArray<Object> tags = null;
        synchronized (sTagsLock) {
            if (sTags == null) {
                sTags = new WeakHashMap<View, SparseArray<Object>>();
            } else {
                tags = sTags.get(view);
            }
        }
        if (tags == null) {
            tags = new SparseArray<Object>(2);
            synchronized (sTagsLock) {
                sTags.put(view, tags);
            }
    private void setKeyedTag(View view, int key, Object tag) {
        if (mKeyedTags == null) {
            mKeyedTags = new SparseArray<Object>();
        }
        tags.put(key, tag);
        mKeyedTags.put(key, tag);
    }
    /**