3

对于使用setTag方法存储的ViewHolder中的活动保持句柄是否安全?在ViewHolder中引用活动

,我发现这个问题,声称该存储到活动的引用会导致内存泄漏,但它已被固定在Android 4.0的:https://code.google.com/p/android/issues/detail?id=18273

具体,我想知道,如果它的安全有ViewHolder看起来是这样的:

class MyHolder { 
    private Context context; // <<-- is this safe to keep here?? 
    private TextView textView; 

    public MyHolder(Context context) { 
    this.context = context; 
    } 

    public void populate(Doc doc) { 
    textView.setText(context.getString(doc.getTextId())); 
    } 

    public View inflate(ViewGroup parent) { 
    View view = LayoutInflater.from(parent.getContext()).inflate(
     R.layout.doc_item, parent, false); 

    textView = (TextView)view.findViewById(R.id.doc_item_text); 

    return view; 
    } 
} 

与getView方法在我的ArrayAdapter这样的:

@Override 
public View getView(int position, View row, ViewGroup parent) { 

    Doc doc = getItem(position); 

    MyHolder holder; 
    if (row != null) { 
     holder = (MyHolder) row.getTag(); 
    } else { 
     holder = new MyHolder(getContext()); 
     row = holder.inflate(parent); 

     row.setTag(holder); 
    } 

    holder.populate(doc); 

    return row; 
} 

(该代码是一个实际代码库的简化版本只是为了得到这个观点。)

我见过的示例代码都没有存储对持有者中的任何内容的引用。我想知道这是巧合还是设计。

回答

4

无论在这种情况下是否安全,最好始终保持上下文引用最小。使用contextMyHolder中处理的所有内容都可以转换为在getView()中执行的操作,同时在适配器中保存上下文引用。这是设计的,因为肯定不需要设计需要多个上下文引用。

+0

当然,对于有些人为的例子感到抱歉。有时,在填充持有者时,我想引用一些更广泛的上下文(例如,用于加载图片的毕加索实例,或者某个内存数据存储库以决定填充视图的准确位置)。在Holder本身上使用填充方法很好,但只有当您可以将引用传递给应用程序的其他部分时,它才会最清晰。 – dsg 2014-09-02 04:58:52

+0

从最简洁的角度来看,你的意思是从代码的角度来看,它只是一个代码块在一个地方而不是另一个的问题,在这种情况下,记住我们的最小上下文引用的目标,最好是拥有它在适配器中。基本上,如果它需要一个上下文,并且可以在'getView()'中完成,则在'getView()'中执行。 – 2014-09-02 05:16:24