【发布时间】:2013-12-14 12:53:11
【问题描述】:
我的 android 应用程序中有一个网格视图。我正在将图像从服务器加载到网格视图。我正在使用延迟加载。我必须回收此处创建的所有位图。如何在适配器或网格视图中执行 Bitmap.recycle()。我的内存不足,请帮帮我。
【问题讨论】:
标签: android
我的 android 应用程序中有一个网格视图。我正在将图像从服务器加载到网格视图。我正在使用延迟加载。我必须回收此处创建的所有位图。如何在适配器或网格视图中执行 Bitmap.recycle()。我的内存不足,请帮帮我。
【问题讨论】:
标签: android
您需要展示一些代码(至少是您的适配器)。如果您遇到内存不足错误,您可能没有正确实现视图回收,或者存在内存泄漏。也有可能您只是一次加载了太多的大位图,但如果您可以加载视图,则更有可能发生内存泄漏。
如果不查看一些代码,任何人都无法追踪内存泄漏。 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
【讨论】:
查看Displaying Bitmaps Efficiently Android 培训课程。它有一个课程Displaying Bitmaps in your UI,涵盖了使用后台线程以及内存和磁盘缓存在 GridView 中显示位图。
【讨论】:
有一种非常简单的方法效果很好:
首先,您必须像这样创建一个自定义 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 的图像测试了这段代码。原来的 ImageView 在显示 50 张带有内存错误的图像后失败,但这段代码在网格结束之前运行良好。
此代码非常适用于小型离线图像,但在线和大型图像需要缓存和其他东西。这可能有用,但必须应用一些更改。
【讨论】: