排球内存不足错误,奇怪的分配尝试 [英] Volley out of memory error, weird allocation attempt

查看:37
本文介绍了排球内存不足错误,奇怪的分配尝试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时 Volley 在启动时随机崩溃我的应用程序,它在应用程序类中崩溃并且用户将无法再次打开应用程序,直到他们进入设置并清除应用程序数据

java.lang.OutOfMemoryError在 com.android.volley.toolbox.DiskBasedCache.streamToBytes(DiskBasedCache.java:316)在 com.android.volley.toolbox.DiskBasedCache.readString(DiskBasedCache.java:526)在 com.android.volley.toolbox.DiskBasedCache.readStringStringMap(DiskBasedCache.java:549)在 com.android.volley.toolbox.DiskBasedCache$CacheHeader.readHeader(DiskBasedCache.java:392)在 com.android.volley.toolbox.DiskBasedCache.initialize(DiskBasedCache.java:155)在 com.android.volley.CacheDispatcher.run(CacheDispatcher.java:84)

diskbasedbache"尝试分配超过 1 GB 的内存,原因不明

我怎么才能不发生这种情况?这似乎是 Volley 的问题,或者可能是基于自定义磁盘的缓存的问题,但我没有立即看到(从堆栈跟踪中)如何清除"此缓存或进行条件检查或处理此异常

洞察力赞赏

解决方案

streamToBytes()中,首先会根据缓存文件的长度来新建字节,是不是你的缓存文件比应用程序大最大堆大小?

private static byte[] streamToBytes(InputStream in, int length) 抛出 IOException {字节[]字节=新字节[长度];...}公共同步条目 get(String key) {CacheHeader entry = mEntries.get(key);文件文件 = getFileForKey(key);byte[] data = streamToBytes(..., file.length());}

如果你想清除缓存,你可以保留 DiskBasedCache 引用,在清除时间到来后,使用 ClearCacheRequest 并将该缓存实例传入:

File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);DiskBasedCache 缓存 = 新的 DiskBasedCache(cacheDir);RequestQueue queue = new RequestQueue(cache, network);队列开始();//清除所有截击缓存.queue.add(new ClearCacheRequest(cache, null));

这种方式会清空所有缓存,建议大家谨慎使用.当然,你可以做条件检查,只需要迭代cacheDir文件,估计过大然后删除.

for (File cacheFile : cacheDir.listFiles()) {如果 (cacheFile.isFile() && cacheFile.length() > 10000000) cacheFile.delete();}

Volley 不是作为大数据缓存解决方案设计的,它是普通的请求缓存,不要随时存储大数据.

------------- 2014-07-17 更新 -------------

其实,清除所有缓存是最终的方式,也不是明智的方式,我们应该在确定会的时候抑制这些大的请求使用缓存,如果不确定呢?我们仍然可以确定响应数据的大小是否大,然后调用setShouldCache(false)禁用它.

public class TheRequest extends Request {@覆盖受保护的响应<字符串>解析网络响应(网络响应响应){//如果响应数据太大,禁用缓存仍然是时间.如果 (response.data.length > 10000) setShouldCache(false);...}}

Sometimes randomly Volley crashes my app upon startup, it crashes in the application class and a user would not be able to open the app again until they go into settings and clear app data

java.lang.OutOfMemoryError
at com.android.volley.toolbox.DiskBasedCache.streamToBytes(DiskBasedCache.java:316)
at com.android.volley.toolbox.DiskBasedCache.readString(DiskBasedCache.java:526)
at com.android.volley.toolbox.DiskBasedCache.readStringStringMap(DiskBasedCache.java:549)
at com.android.volley.toolbox.DiskBasedCache$CacheHeader.readHeader(DiskBasedCache.java:392)
at com.android.volley.toolbox.DiskBasedCache.initialize(DiskBasedCache.java:155)
at com.android.volley.CacheDispatcher.run(CacheDispatcher.java:84)

The "diskbasedbache" tries to allocate over 1 gigabyte of memory, for no obvious reason

how would I make this not happen? It seems to be an issue with Volley, or maybe an issue with a custom disk based cache but I don't immediately see (from the stack trace) how to 'clear' this cache or do a conditional check or handle this exception

Insight appreciated

解决方案

In the streamToBytes(), first it will new bytes by the cache file length, does your cache file was too large than application maximum heap size ?

private static byte[] streamToBytes(InputStream in, int length) throws IOException {
    byte[] bytes = new byte[length];
    ...
}

public synchronized Entry get(String key) {
    CacheHeader entry = mEntries.get(key);

    File file = getFileForKey(key);
    byte[] data = streamToBytes(..., file.length());
}

If you want to clear the cache, you could keep the DiskBasedCache reference, after clear time's came, use ClearCacheRequest and pass that cache instance in :

File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
DiskBasedCache cache = new DiskBasedCache(cacheDir);
RequestQueue queue = new RequestQueue(cache, network);
queue.start();

// clear all volley caches.
queue.add(new ClearCacheRequest(cache, null));

this way will clear all caches, so I suggest you use it carefully. of course, you can doing conditional check, just iterating the cacheDir files, estimate which was too large then remove it.

for (File cacheFile : cacheDir.listFiles()) {
    if (cacheFile.isFile() && cacheFile.length() > 10000000) cacheFile.delete();
}

Volley wasn't design as a big data cache solution, it's common request cache, don't storing large data anytime.

------------- Update at 2014-07-17 -------------

In fact, clear all caches is final way, also isn't wise way, we should suppressing these large request use cache when we sure it would be, and if not sure? we still can determine the response data size whether large or not, then call setShouldCache(false) to disable it.

public class TheRequest extends Request {
    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        // if response data was too large, disable caching is still time.
        if (response.data.length > 10000) setShouldCache(false);
        ...
    }
}

这篇关于排球内存不足错误,奇怪的分配尝试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆