【问题标题】:Does using the ViewHolder pattern cause a memory leak after android orientation change?android 方向更改后使用 ViewHolder 模式会导致内存泄漏吗?
【发布时间】:2016-02-02 01:45:19
【问题描述】:

来自https://developer.android.com/training/improving-layouts/smooth-scrolling.html#ViewHolder

> A ViewHolder object stores each of the component views inside the 
> tag field of the Layout, so you can immediately access them without 
> the need to look them up repeatedly. 

在 android 中更改方向后,将重新创建列表视图,因此所有列表视图项目 丢失了。

例子:

/** ViewHolder attached to ListView-Item.tag */
public static class MyViewHolder {
    /** the image belonging to ListView-Item */
    ImageView mListViewItemImage;
}

我的问题:这是否会导致内存泄漏,因为存在循环引用:

  • ListView-Item.tag 引用 MyViewHolder
  • MyViewHolder.mListViewItemImage 引用了在方向更改后丢弃的旧 gui。

如果这导致内存泄漏,我是否必须实现 ViewHolder 垃圾回收?

【问题讨论】:

    标签: android listview memory-leaks android-orientation


    【解决方案1】:

    这种模式不使用静态变量,只有类是静态内部类。

    在您提到的参考文献中,明确指出您应该像这样创建ViewHolder 类的实例:

    ViewHolder holder = new ViewHolder();
    

    然后您将拥有一个 ViewHolder 类的实例,这意味着垃圾收集器可以收集它,因此如果没有更多对它的引用,它就不会保留在内存中。如果ViewHolder 实例没有对它的引用,则可以收集它以及仅具有来自ViewHolder 对象(ImageViews)的引用的对象。

    所以我的一般回答是:ViewHolder 模式如果你正确使用它不会导致内存泄漏。

    【讨论】:

    • 内存泄漏不仅限于静态变量。据我所知,android 不能回收像 a.ref = bb.ref= a 这样的循环引用
    • 如果a 是你的ViewHolder 对象,b 是你的ImageView:你有一个从ViewHolderImageView 的引用,但在ImageView 你没有提到ViewHolder,对吧?这种方式没有循环依赖。但是即使是这样,GC 也是一个聪明的东西,如果有没有从任何地方使用的圆圈,它会找到并销毁它们。
    • 如果我说 imageview 引用了活动 (getContext()) 引用了 listview 引用了 listview-items 引用了 viewholder 引用了 imageview,我错了吗?我不确定GC是否足够聪明来解决这个问题。这就是我问这个问题的原因。
    • 您的 ViewHolder 仍然会被收集,因为在 Android 重新创建您的列表视图后没有更多对它的引用。当方向改变发生时,Android 会处理视图的 gc。 Check this
    猜你喜欢
    • 2014-01-22
    • 2017-11-24
    • 1970-01-01
    • 2010-11-18
    • 2021-03-23
    • 2021-09-25
    • 2014-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多