gpt4 book ai didi

android - java.lang.OutOfMemoryError : bitmap size exceeds VM budget in ListView and lazy loading images 错误

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:06:52 24 4
gpt4 key购买 nike

我有一个 ListView ,它可能在无限滚动时加载了无限项。

ListView 中的每个项目都有一两张我懒加载的图片。

一切都很好,但是当我滚动很长时间时,它会在 log cat 中崩溃

 08-07 15:26:25.231: E/AndroidRuntime(30979): FATAL EXCEPTION: Thread-60
08-07 15:26:25.231: E/AndroidRuntime(30979): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
08-07 15:26:25.231: E/AndroidRuntime(30979): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
08-07 15:26:25.231: E/AndroidRuntime(30979): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
08-07 15:26:25.231: E/AndroidRuntime(30979): at com.test.android.helper.LazyImageLoader.decodeFile(LazyImageLoader.java:171)
08-07 15:26:25.231: E/AndroidRuntime(30979): at com.test.android.helper.LazyImageLoader.getBitmap(LazyImageLoader.java:112)
08-07 15:26:25.231: E/AndroidRuntime(30979): at com.test.android.helper.LazyImageLoader.access$2(LazyImageLoader.java:106)
08-07 15:26:25.231: E/AndroidRuntime(30979): at com.test.android.helper.LazyImageLoader$ImageLoader.run(LazyImageLoader.java:197)

在我的惰性图像加载器中,我将位图存储在 WeakHashMap 中。那么垃圾收集器应该收集位图吗?

我的惰性图像加载器是这样工作的。

我使用 url 和对 imageview 的引用从我的适配器调用 displayImage()

public void displayImage(String url, ImageView imageView, int defaultImageResourceId){

latestImageMetaData.put(imageView, url);

if(weakhashmapcache.containsKey(url)){
imageView.setImageBitmap(weakhashmapcache.get(url));
}
else{
enqueueImage(url, imageView, defaultImageResourceId);
imageView.setImageResource(defaultImageResourceId);
}
}

所以如果我在缓存中找到图像,我直接设置它,否则我用函数 enqueueImage() 将它排队。

private void enqueueImage(String url, ImageView imageView, int defaultImageResourceId){ 图片 image = new Image(url, imageView, defaultImageResourceId); 下载队列。添加(图像); //downloadQueue 是一个等待添加图像的阻塞队列 //如果队列即将满,则删除队列中前面的元素,因为它们无论如何都不可见 迭代器 iterator = downloadQueue.iterator(); while(iterator.hasNext() && downloadQueue.remainingCapacity() < 80){ downloadQueue.remove(iterator.next()); }

And my image loader thread is this - 

class ImageLoader extends Thread {

public void run() {
Image firstImageInQueue;

try {
while((firstImageInQueue = downloadQueue.take()) != SHUTDOWN_TOKEN)
{
Bitmap imageBitmap = getBitmap(firstImageInQueue.url);

if(imageBitmap != null){
weakhashmap.put(firstImageInQueue.url, imageBitmap);
BitmapDisplayer displayer = new BitmapDisplayer(imageBitmap, firstImageInQueue.imageView, firstImageInQueue.url, firstImageInQueue.defaultImageResourceId);
Activity activity = (Activity)firstImageInQueue.imageView.getContext();
activity.runOnUiThread(displayer);
}
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
finally {
imageLoaderTerminated = true;
}
}
}

getBitmap() 只是从 url scales 获取图像并将其解码为 Bitmap 对象。 BitmapDisplayer 只是一个 Runnable,它在 UI 线程上将图像设置为 imageview。

我做错了什么?

最佳答案

这是一场噩梦,经过日日夜夜的研究,这里有几点可能对其他人有用。

不要将所有位图都存储在缓存中。保持它在磁盘缓存和内存缓存之间交换。您存储的位图数量可能取决于您通过调用

获得的堆限制

int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))
.getMemoryClass();

我用了 LruCache而不是 WeakHashMap 缓存。 LruCache 在支持包中可用。用 LruCache 替换现有的 WeakHashMap 实现非常容易。 Android 在 Caching Bitmaps 上也有漂亮的文档.

jack 沃顿的 DiskLruCache是管理磁盘缓存的好方法。

如果不需要,请不要下载巨大的位图。尽量选择刚好适合您需要的尺码。

使用 BitmapFactory.Options,您可以在图像质量方面做出一些权衡,以便在内存缓存中保存更多图像。

如果您认为我们还有什么可以做的,欢迎补充。

关于android - java.lang.OutOfMemoryError : bitmap size exceeds VM budget in ListView and lazy loading images 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11884192/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com