Android - GC滞后listview滚动“更大”的图像

时间:2012-12-29 01:29:02

标签: android image listview garbage-collection lag

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

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

我理解一些事情:   - 应用程序堆大小=有限,首次运行时分配= 13MB,剩余1 MB。   - 我有GC_FOR_ALLOC日志消息,系统停止15ms。 (我认为这是我滚动的lagg)。 - 更改代码后,我也看到了GC_CONCURRENT消息。

使用这些GC消息,我理解每次滚动到新listview条目中的另一个图像时我的垃圾收集。 到目前为止,我可以对此进行分析,但我不确切知道如何修复并永久删除GC。 我已将图像缩小到100x100,并将GC消息推迟了更长时间。 但最终GC开始了。 我使用convertview回收视图,并在视图中使用持有者。

我已经阅读了有关重新使用图像内存的信息,但不确定是否以及如何执行此操作。 或者,当在列表视图中使用这些较大的图像时,maby是“正常”的,我需要重新考虑图像的绘制,并且只在刻录结束时才开始绘制?

我是否应该使用Listview滚动图片?

2012-12-31_02:11我已经实现了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>

2 个答案:

答案 0 :(得分:2)

你一直在打开Bitmaps,那些占用了大量需要收集的内存,以便为你下次要加载的大量Bitmaps留出空间。< / p>

如果加载图片不以全尺寸显示,您可以先使用BitmapFactory Options对加载图片进行二次采样。这样,您只需占用尽可能多的内存来填充视图,从而减少 GC 调用。

您还可以尝试在适配器中保留某种缓存,以避免每次都重新加载Bitmaps

答案 1 :(得分:0)

有很多技术可以让ListView更快。见Efficient ListView in android。您应该回收视图,这将减少垃圾收集。您也可以考虑在列表滚动停止之前不加载图像,请参阅Lazy Load images on Listview in android(Beginner Level)?