如何在gridview适配器中回收位图?

时间:2012-01-31 05:06:55

标签: android

我在我的Android应用程序中有一个网格视图。我正在从服务器将图像加载到网格视图。我正在使用延迟加载。我必须回收在这里创建的所有位图。如何在Adapter或Grid视图中执行Bitmap.recycle()。我失去了记忆,请帮助我。

3 个答案:

答案 0 :(得分:6)

您需要显示一些代码(至少是您的适配器)。如果您出现内存不足错误,则可能无法正确实现视图回收,或者内存泄漏。您也可能只是一次只加载太多大位图,但如果您可以加载视图,则更有可能发生内存泄漏。

如果不查看某些代码,任何人都无法追踪内存泄漏。 Bitmap.recycle()不是一个解决方案,如果代码的其余部分没问题,垃圾收集器将无法正常工作。

请参阅:http://www.youtube.com/watch?v=_CruQY55HOk,了解如何在Android中管理内存并查找内存泄漏。

另请尝试:http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html以获取如何下载或以其他方式正确异步将图像加载到视图列表中的示例。

编辑:还查看我写的图片加载库,因此您无需担心任何问题:https://github.com/bumptech/glide

答案 1 :(得分:5)

查看Displaying Bitmaps Efficiently Android培训课程。它有一个课程Displaying Bitmaps in your UI,它涵盖了使用后台线程和内存和磁盘缓存在GridView中显示位图。

答案 2 :(得分:2)

有一种非常简单的方法可以很好地运作:

首先,您必须创建如下自定义ImageView:

public class ImageViewRecyclable extends ImageView
{
    private Bitmap bitmap;

    public ImageViewRecyclable(Context context)
    {
        super(context);
    }

    @Override
    public void setImageBitmap(Bitmap bm)
    {
        super.setImageBitmap(bm);
        if (bitmap != null) bitmap.recycle();
        this.bitmap = bm;
    }
}

我们的ImageViewRecyclable保留一个指向位图的指针,并在设置新位图之前回收旧位图。

其次,您必须检查适配器的getView以查看convertView是否为null。如果它不是null,则转换为我们的自定义ImageViewRecyclable并在其上设置位图。这样,旧的位图在设置新位图之前就会被回收。

这是适配器的getView代码:

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    ImageViewRecyclable imageView = (convertView == null) ? new ImageViewRecyclable(ActivityMain.this) : (ImageViewRecyclable) convertView;
    byte[] bytes = ....
    Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    imageView.setImageBitmap(bitmap);

    return imageView;
}

我用1000张100x100图像测试了这段代码。显示50张图像并显示内存错误后,原始ImageView失败,但此代码在网格结束前工作良好。

此代码适用于小型离线图像,但在线和大型图像需要缓存和其他功能。这可能很有用,但必须进行一些更改。