Sud*_*hat 5 android listview bitmap out-of-memory android-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)
Run Code Online (Sandbox Code Playgroud)
在我的懒惰图像加载器中,我将位图存储在a中WeakHashMap.垃圾收集器应该收集位图吗?
我懒惰的图像加载器就是这样的.
我displayImage()从我的适配器调用url和imageview的引用
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);
}
}
Run Code Online (Sandbox Code Playgroud)
所以如果我在缓存中找到图像,我会直接设置它,否则我会用函数对它进行排队enqueueImage().
private void enqueueImage(String url,ImageView imageView,int defaultImageResourceId){Image image = new Image(url,imageView,defaultImageResourceId); downloadqueue.add(图像); // downloadQueue是一个阻塞队列它等待要添加的图像//如果队列即将获得充分然后删除是提前在队列中,因为它们是反正元件不可见迭代迭代= 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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
getBitmap()只需从url scale中提取图像并将其解码为Bitmap对象.BitmapDisplayer只是一个Runnable,它在UI线程上设置图像到imageview.
我究竟做错了什么?
这是一场噩梦,经过几天几夜的研究,这里有一些可能对其他人有用的要点。
不要将所有位图存储在缓存中。保持它在磁盘缓存和内存缓存之间交换。您存储的位图数量可能取决于您通过调用获得的堆限制
int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))
.getMemoryClass();
我用aLruCache代替WeakHashMap缓存。LruCache可在支持包中找到。WeakHashMap用 替换现有的实现非常容易LruCache。Android 还有一个关于缓存位图的精美文档。
Jake Wharton 的DiskLruCache方法是管理磁盘缓存的好方法。
如果不需要,请不要下载巨大的位图。尝试选择刚好适合您需要的尺寸。
使用 BitmapFactory.Options,您可以对图像质量进行一些权衡,以在内存缓存中保存更多图像。
如果您认为我们还有什么可以做的,请补充。
| 归档时间: |
|
| 查看次数: |
1244 次 |
| 最近记录: |