17

ときどきランダムに Volley が起動時にアプリをクラッシュさせ、アプリケーション クラスでクラッシュし、ユーザーは設定に移動してアプリ データを消去するまでアプリを再度開くことができません。

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)

「diskbasedbache」は、明らかな理由もなく、1 ギガバイトを超えるメモリを割り当てようとします。

これが起こらないようにするにはどうすればよいですか?Volleyの問題、またはカスタムディスクベースのキャッシュの問題のようですが、(スタックトレースから)このキャッシュを「クリア」する方法、条件付きチェックを行う方法、またはこの例外を処理する方法がすぐにはわかりません

洞察力に感謝

4

3 に答える 3

16

ではstreamToBytes()、最初にキャッシュ ファイルの長さによって新しいバイトになります。キャッシュ ファイルがアプリケーションの最大ヒープ サイズよりも大きすぎませんか?

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());
}

キャッシュをクリアしたい場合は、DiskBasedCache参照を保持し、クリア時間になった後、ClearCacheRequestそのキャッシュ インスタンスを使用して渡すことができます。

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));

この方法ではすべてのキャッシュがクリアされるため、慎重に使用することをお勧めします。もちろん、cacheDirconditional checkファイルを反復するだけで、どれが大きすぎるかを推定して削除することができます。

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

Volley はビッグ データ キャッシュ ソリューションとして設計されたものではありません。これは一般的なリクエスト キャッシュであり、いつでも大規模なデータを保存する必要はありません。

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

実際、すべてのキャッシュをクリアすることは最終的な方法であり、賢明な方法でもありません。確実な場合は、これらの大量のリクエストによるキャッシュの使用を抑制する必要があります。応答データのサイズが大きいかどうかを判断し、呼び出しsetShouldCache(false)て無効にすることができます。

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);
        ...
    }
}
于 2014-06-26T04:27:03.553 に答える
1

問題が発生すると、その後の初期化ごとに再発し、キャッシュされた無効なヘッダーを指しているように見えます。

幸いなことに、この問題は公式の Volley リポジトリで修正されています。

android-volley ミラーで関連する問題を参照してください。

于 2017-02-13T05:02:53.197 に答える