安卓Volley 给我一个内存溢出异常

10

我正在使用Volley从服务器上显示水平滑动视图中的图像,但我的图像相当大,这就是为什么我会遇到内存不足异常的原因。

以下是我的Volley类:

public class Volley{

private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;

public Volley(Context ctx) {
    Log.v("Volley", "Volley onCreate");
    mRequestQueue = com.android.volley.toolbox.Volley.newRequestQueue(ctx);

    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    final int cacheSize = maxMemory / 8;

    ImageLoader.ImageCache imageCache = new ImageLoader.ImageCache() {
        LruCache<String, Bitmap> imageCache = new LruCache<String, Bitmap>(cacheSize);

        @Override
        public void putBitmap(String key, Bitmap value) {
            imageCache.put(key, value);
        }

        @Override
        public Bitmap getBitmap(String key) {
            return imageCache.get(key);
        }
    };

    mImageLoader = new ImageLoader(mRequestQueue, imageCache);

}

public void clear(Context ctx) {
    mRequestQueue.cancelAll(ctx);
    mImageLoader = null;
    mRequestQueue = null;
}

public RequestQueue getRequestQueue() {
    return mRequestQueue;
}

public ImageLoader getImageLoader() {
    return mImageLoader;
}}

图片加载器代码:

image.setImageUrl(imagePhoto.url, getVolley(getContext()).getImageLoader());

public Volley getVolley(Context ctx) {
    if(mVolley == null) {
        mVolley = new Volley(getContext());
    }
    return mVolley;
}

异常:

> 06-10 22:14:27.462: E/AndroidRuntime(10060): FATAL EXCEPTION: Thread-29479
06-10 22:14:27.462: E/AndroidRuntime(10060): java.lang.OutOfMemoryError
06-10 22:14:27.462: E/AndroidRuntime(10060):    at com.android.volley.toolbox.ByteArrayPool.getBuf(ByteArrayPool.java:101)
06-10 22:14:27.462: E/AndroidRuntime(10060):    at com.android.volley.toolbox.PoolingByteArrayOutputStream.<init>(PoolingByteArrayOutputStream.java:53)
06-10 22:14:27.462: E/AndroidRuntime(10060):    at com.android.volley.toolbox.BasicNetwork.entityToBytes(BasicNetwork.java:202)
06-10 22:14:27.462: E/AndroidRuntime(10060):    at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:104)
06-10 22:14:27.462: E/AndroidRuntime(10060):    at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:105)
3个回答

5
我已经修复了这个问题,为BitmapLruCache提供了正确的缓存,而不是使用LruCache。
public class BitmapLruCache extends LruCache<String, Bitmap> implements ImageLoader.ImageCache {
public static int getDefaultLruCacheSize() {
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    final int cacheSize = maxMemory / 8;

    return cacheSize;
}

public BitmapLruCache() {
    this(getDefaultLruCacheSize());
}

public BitmapLruCache(int sizeInKiloBytes) {
    super(sizeInKiloBytes);
}

@Override
protected int sizeOf(String key, Bitmap value) {
    return value.getRowBytes() * value.getHeight() / 1024;
}

@Override
public Bitmap getBitmap(String url) {
    return get(url);
}

@Override
public void putBitmap(String url, Bitmap bitmap) {
    put(url, bitmap);
}

这里是链接: Android Volley ImageLoader - BitmapLruCache参数?


该链接讨论了在使用 Android Volley 的 ImageLoader 时如何设置 BitmapLruCache 参数。

1
我使用了你的解决方案,但它并没有解决我的问题:http://stackoverflow.com/questions/17991328/how-to-deal-with-outofmemory-exception 。你能帮帮我吗? - Ziem
1
@pjco - 确保将Volley队列和Loader保持在应用程序级别。 - AJit
@pjco - 但我认为 Volley 应该自己处理 OOM。我在 Application 类中初始化了 Volley 队列(Volley.newRequestQueue)和 ImageLoader。 - Ziem
它应该并且确实捕获了错误。然而,保持缓存全局和/或有点保守总是好的。但上述技术是由 Volley 不控制的内存缓存,并且将使用与 Volley 解码内存不同的内存。我认为问题主要出在旧设备上,这些设备对图像解码过程没有那么多的控制(因此您会在 volley logcat 中看到类似“vm 不允许我们分配…”的内容)。 - pjco
可能是的,我还没有在旧设备或虚拟机上测试过。 - AJit
显示剩余3条评论

0

我不确定你是如何实现滑动视图的。但在大多数实现中(例如viewpager),它会缓存3个或更多的项。因此,您实际上不需要为volley提供LRUCache。

只需删除imageCache的代码,您将看到内存使用方面的改进。


实际上,Volley仅提供磁盘缓存,我们仍然需要为Volley设置内存缓存,感谢您的回答 :) - AJit

0
我不知道你的ImageLoader是如何实现的,但它可能会加载一个位图。尝试在生成位图时将以下BitmapOption设置为true:inPurgeable。这样,当内存不足时,位图内存将被清除。
看看这个问题:为什么我要使用BitmapFactory的inPurgeable选项?

ImageLoader是由Volley本身实现的,感谢答复 :) - AJit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接