安卓 - GC 滞后于列表视图滚动与"bigger"图像



在listview中,我想在列表条目上绘制一个图像。在垂直模式下,这20张图片必须缩放以填充宽度。手机分辨率为480 x 800像素(SGS2)。图像分辨率为400x400,大小约为100KB。我已经把图片放到了drawable文件夹中。

当我滚动列表时,它并不顺利。

我明白一些事情:-应用程序堆大小=有限,第一次运行时分配= 13MB,剩下1mb-我有GC_FOR_ALLOC日志消息,它使系统停止15ms。(我想这是我在滚动方面的滞后)。-更改代码后,我还看到GC_CONCURRENT消息。

有了这些GC消息,我知道每次滚动到新的listview条目中的另一个图像时,垃圾收集就会启动。到目前为止,我可以分析这个问题,但我不知道该怎么做才能永久地修复和删除GC。我将图像缩小到100x100,这将延迟GC消息更长的时间。但最终GC开始发挥作用。我确实使用convertview来回收视图,并且已经在视图中使用了holder。

我读过关于重用图像内存,但不确定是否以及如何做到这一点。或者,当在列表视图中使用这些较大的图像时,它可能是"正常的",我需要重新考虑图像的绘制,并且只有在滚动结束时才开始绘制?

我应该使用Listview滚动图片吗?

我已经实现了setOnScrollListener,它使滚动平滑。我认为我必须进一步研究这段代码,以润色它。

listview适配器
public class ListviewAdapter extends BaseAdapter {
    private static Activity activity;
    private int[] data;
    private static LayoutInflater mInflater = null;
    public ListviewAdapter(Activity a, int[] d) {
        activity = a;
        data = d;
        mInflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    public int getCount() {
        return data.length;
    }
    public Object getItem(int position) {
        return position;
    }
    public long getItemId(int position) {
        return position;
    }
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.listviewitem, parent,
                    false);
            holder = new ViewHolder();
            holder.picture = (ImageView) convertView.findViewById(R.id.image);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        if (!MainActivity.isScrolling) {
    holder.picture.setImageResource(data[position]);
    }
        return convertView;
    }
    static class ViewHolder {
        ImageView picture;
    }
}

listview XML

<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
  <ImageView
      android:id="@+id/image"
      android:src="@drawable/stub"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:contentDescription="Animal images"
        android:scaleType="fitCenter"
        android:scrollingCache="false"
        android:animationCache="false" 
        />
</LinearLayout>

你一直在打开Bitmaps,这些需要收集大量的内存,以便有空间给你将加载的Bitmaps

您可以开始使用BitmapFactory Options子采样加载图像,如果它不打算以全尺寸显示。这样,您只需占用所需的内存来填充视图,从而减少GC调用。

你也可以尝试在你的适配器中保留一些缓存,以避免每次重新加载Bitmaps

有很多技术可以使listview更快。参见android中的高效列表视图。您应该回收视图,这将减少垃圾收集。你也可以考虑在列表滚动停止之前不加载图像,参见android(初学者级别)的Listview中的延迟加载图像?

最新更新