2

我面临一个非常奇怪的问题。我有一个Activity,ActionBar包含一个自定义视图。

如果我像这样加载这个自定义视图的 XML:

LayoutInflater inflater = LayoutInflater.from(this);
ViewGroup vg = (ViewGroup) inflater.inflate(R.layout.action_search_form,null);

它泄漏:活动不是 GC'd。以下修复有效(为什么?):

LayoutInflater inflater = LayoutInflater.from(getApplicationContext());

但是,如果我OnClickListener在子视图上设置 a ,它会再次泄漏:

ImageButton clear = (ImageButton) vg.findViewById(...);
clear.setOnClickListener(new View.OnClickListener() {

   @Override
   public void onClick(View v) {
            // Even if empty
        }
    });
}

所有这些都发生在活动的私有方法中,所有视图都是局部变量。

我找到了一个修复方法,但不明白它为什么起作用:视图很简单,所以我用 Java 编写了它,而不是夸大 XML。我怀疑这与没有上下文传递给 LayoutInflater 并且 Activity 本身没有发生任何事情有关,但是如果有人可以帮助我理解发生了什么,我将不胜感激。

4

1 回答 1

4

所有 View 类都需要一个 Context 参数。当您对 XML 进行膨胀时,提供给创建视图的上下文与提供给 LayoutInflater 的上下文相同。您的视图保留了对您的活动的引用。

当您使用 getApplicationContext() 并且 Activity 不泄漏的原因是因为您传递的上下文对应用程序的整个生命周期都是全局的,而不仅仅是活动。

** 编辑 **

至于为什么 OnClickListener 还保留您的 Activity,这是因为使用匿名内部类的副作用。默认情况下,这些内联实现保留对父/包装类实例的引用。这样您就可以从内部的实现中调用父级的方法。

例如:

myView.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        MyActivity.this.doSomethingCool();
    }
}

无论方法体中是否有任何内容,内部类仍然保持对父类的引用。

于 2013-01-17T18:51:36.610 回答