列表视图中有大量垃圾回收

Ben*_*fez 21 android listview garbage-collection

我有一个使用自定义适配器的ListView.自定义适配器的getView使用了所有建议的做法:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    SuscriptionsViewsHolder holder;
    ItemInRootList item = mItemsInList.get(position);

    if (convertView == null) {
         convertView = mInflater.inflate(R.layout.label, null);

         holder = new SuscriptionsViewsHolder();
         holder.label = (TextView) convertView.findViewById(R.id.label_label);
         holder.icon = (ImageView) convertView.findViewById(R.id.label_icon);

        convertView.setTag(holder);
    } else {
        holder = (SuscriptionsViewsHolder) convertView.getTag();
    }

    String text = String.format("%1$s (%2$s)", item.title, item.unreadCount);
    holder.label.setText(text);
    holder.icon.setImageResource(item.isLabel ? R.drawable.folder : R.drawable.file );

    return convertView;
}
Run Code Online (Sandbox Code Playgroud)

但是当我滚动时,由于垃圾收集量很大,它很迟钝:

GC_EXTERNAL_ALLOC freed 87K, 48% free 2873K/5447K, external 516K/519K, paused 30ms
GC_EXTERNAL_ALLOC freed 7K, 48% free 2866K/5447K, external 1056K/1208K, paused 29ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2866K/5447K, external 1416K/1568K, paused 28ms
GC_EXTERNAL_ALLOC freed 5K, 48% free 2865K/5447K, external 1600K/1748K, paused 27ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2865K/5447K, external 1780K/1932K, paused 30ms
GC_EXTERNAL_ALLOC freed 2K, 48% free 2870K/5447K, external 1780K/1932K, paused 26ms
GC_EXTERNAL_ALLOC freed 2K, 48% free 2870K/5447K, external 1780K/1932K, paused 25ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 26ms
GC_EXTERNAL_ALLOC freed 3K, 48% free 2870K/5447K, external 1780K/1932K, paused 25ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 29ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 29ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2871K/5447K, external 1780K/1932K, paused 28ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2871K/5447K, external 1780K/1932K, paused 26ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 27ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 29ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 26ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 34ms
Run Code Online (Sandbox Code Playgroud)

什么似乎是错的?

编辑格林威治标准时间12:47:

实际上它比这稍微复杂一点.我的应用UI基于2个部分.一个是屏幕的大脑,创建视图,处理用户输入等.另一个是Fragment如果设备有android 3.0,否则它是一个Activity.

GC发生在我的Nexus One 2.3.3设备上,因此请使用Activity.我没有和我一起测试行为Fragment.

如果需要,我可以发布源代码,但让我试着解释一下:

  • RootList是UI的大脑.它包含 :
    • 一个List<>项目将被放置在ListView.
    • 从SQLite数据库构建此列表的方法
    • 一个自定义的BaseAdapter,它基本上只包含上面粘贴的getView方法
  • RootListActivity是一个ListActivity,其中:
    • 使用XML布局
    • 布局当然是带有id的listview android.id.list
    • 使用创建活动时创建的RootList实例将Activity回调转发到RootList类(构造函数,不是onCreate)
    • onCreate,我调用RootList的方法将创建项目列表,并将列表数据设置为我的自定义类的新实例派生自BaseAdapter

格林尼治标准时间5月17日下午9:36编辑:

这是Activity的代码和执行这些操作的类.http://pastebin.com/EgHKRr4r

Ben*_*fez 21

我发现了这个问题.我的活动XML布局是:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <include android:id="@+id/rootlist_header" layout="@layout/pre_honeycomb_action_bar" />

    <ListView android:id="@android:id/list"
        android:layout_below="@id/rootlist_header"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        android:textColor="#444444"
        android:divider="@drawable/list_divider"
        android:dividerHeight="1px"
        android:cacheColorHint="#00000000" />

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

如果我删除了android:cacheColorHint="#00000000",那么重型GC就会出来,滚动很顺畅!:)

我真的不知道为什么设置这个参数,因为我不需要它.也许我复制了太多而不是实际构建我的XML布局.

感谢您的支持,非常感谢您的帮助.

  • 哇靠!!!删除这个邪恶的cacheColorHint后,不稳定性消失了.从ListView XML定义中仅删除此值后,GC_EXTERNAL_ALLOC的数量减少了5-10倍.我将BitmapFactory.Options inPurgeable = true添加到我的Bitmap创建后,垃圾收集变得疯狂,并且由于GC导致滚动速度非常慢.你刚刚保存了我(我甚至首先跳过了这个答案,因为我认为cacheColorHint是每个XML行的属性,而不是ListView本身的属性!).那将教会我更仔细地阅读. (2认同)

小智 11

我也遇到了问题android:cacheColorHint="#00000000".我需要使用它,因为我有一个固定的背景图像.

我发现设置以下属性会禁用android的列表视图缓存,并且列表滚动顺畅(不再调用GC):

android:scrollingCache="false"
android:animationCache="false"
Run Code Online (Sandbox Code Playgroud)

此外,如果你想摆脱默认的选择颜色使用这个:

android:listSelector="#00000000"
Run Code Online (Sandbox Code Playgroud)


Rom*_*Guy 8

您应该使用DDMS及其分配跟踪器来确切地确定生成这么多对象的内容.但请注意,String.format()以生成大量垃圾而闻名.

http://developer.android.com/resources/articles/track-mem.html