View + Tag =内存泄漏?

Ole*_*ndr 4 android memory-leaks view

基础:

  • 活动 - 在每个orientatin变化上重新创建(onCreate-onDestroy)
  • View包含带有两个子项的ViewFlipper:简单的RelativeLayout和ListView
  • ListView行具有复杂的布局和关联的标记

问题是我在每个方向更改时都有内存泄漏 - 活动在整个视图布局中保留在内存中.活动本身就是一个上下文,所以只要关联对象就会保留在内存中.所以现在我想找到泄密事件发生的原因.

View有setTag()方法.我用它来存储一些关于行的信息(因此ListView中的每一行(View)都有关联的标签).

但是视图和GC如何与标签一起使用?我的标记对象(持有者)包含对视图的引用,但如果视图删除了对它的标记的引用,则将很容易收集此引用(带有标记本身).

任何人都遇到类似ListViews的问题?

PS我想知道GC如何清理布局 - 循环引用,上下文,持有者等等......

Mic*_*ael 9

首先,如果使用View.setTag(int, Object)方法,可以泄漏对象.使用此方法设置的标记存储在WeakHashMap带有View键的静态中.因此,如果您在父视图的标记中存储对子视图的引用,那么所有这些视图以及它们(父活动)创建的上下文都将被泄露.这是因为每个子视图都包含对其父视图的引用,因此GC将永远不会收集父视图.

有一种简单的方法可以模拟这种行为:

public static class MainActivity extends ListActivity {
    private final WeakHashMap<Parent, Parent.Child> mMap =
        new WeakHashMap<Parent, Parent.Child>();

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // If parents were collected OOM error wouldn't be thrown.
        // But they aren't collected so we get OOM here.
        for (int i = 0; i < 10; ++i) {
            Parent parent = new Parent();
            mMap.put( parent, parent.mChild );
        }
    }
}

public static class Parent {
    public final Child mChild = new Child();

    public class Child {
        private final byte[] mJunk = new byte[10*1024*1024];
    }
}
Run Code Online (Sandbox Code Playgroud)

其次,似乎ListView该类导致内存泄漏.这意味着列表视图,其所有可回收的子项及其父活动都被泄露.以下是有关此错误的一些信息: