排球 - parseNetworkResponse OutOfMemoryError

Volley - parseNetworkResponse OutOfMemoryError

我正在使用 Volley 来管理我的应用程序。有时,当响应过大时,我会在没有太多 RAM 的设备上遇到 OOM。我不确定如何解决这个问题。我知道 Volley 将它的响应存储在内存中,但是我的应用程序非常依赖 Volley,以至于切换起来会很痛苦。我在使用 Retrofit 时也遇到了问题。我试过使用 JsonReader,但它似乎仍然会发生。我有一个与 Volley 一起使用的自定义请求。它 returns 一个 Gson JsonObject。这是我目前的代码,当响应数据长度返回 5511532 (5mb) 时,应用程序收到 OOM。

@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
    try {
        String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));

        if (LOG_HEADERS) {
            Log.d("GsonResponseHeaders", response.headers.toString());
        }
        if (LOG_JSON) {
            Log.d("GsonRequestResponse", json);
        }

        return Response.success(gson.fromJson(json, clazz), HttpHeaderParser.parseCacheHeaders(response));
    } catch (UnsupportedEncodingException e) {
        return Response.error(new ParseError(e));
    } catch (JsonSyntaxException e) {
        return Response.error(new ParseError(e));
    } catch (OutOfMemoryError e) {
        Log.d("ResponseLength", "-- " + response.data.length);
        return Response.error(new ParseError(e));
    }
}

编辑:

这是抛出 OOM 的示例响应。

GsonRequestResponse: {"user_company_info":[{"id":"1","company_id":"5","circle_id":"34","status":"A","cat_id":"1","company_map":"0","timestamp":"2015-07-09 15:28:40","added_by":"1","add_date":"0000-00-00","name":"FSM","added_datetime":"2014-02-12 16:16:51","clause":"fsm_company","company_name":"Assero Services LLC - FSM","circles":[{"id":"1","company_id":"5","circle_id":"34","status":"A","cat_id":"1","company_map":"0","timestamp":"2015-07-09 15:28:40","added_by":"1","add_date":"0000-00-00","circle_name":"Cityside - HUD Contract Area - 5D","create_by":"2536","create_date":"0000-00-00","circle_owner":"0","circle_owner_company":"26792","circle_company_identifier":"0","level":"OUTER","assign_fsm":"26792","assign_client":"25491","assign_am":"0","routine_1":"10065","routine_2":"10209","routine_3":"10062","routine_4":"0","image_duplicate_api":"Y","routine_1_type":null,"routine_1_method":null,"routine_1_cancel_buffer":null,"routine_2_type":null,"routine_2_method":null,"routine_2_cancel_buffer":null,"routine_3_type":null,"routine_3_method":null,"routine_3_cancel_buffer":null,"routine_4_type":null,"routine_4_method":null,"routine_4_cancel_buffer":null,"name":"FSM","added_datetime":"2014-02-12 16:16:51","clause":"fsm_company","can_issue":"1"},{"id":"1","company_id":"5","circle_id":"33","status":"A","cat_id":"1","company_map":"0","timestamp":"2015-07-09 15:28:40","added_by":"1","add_date":"0000-00-00","circle_name":"Cityside - HUD Contract Area - 4D","create_by":"2536","create_date":"0000-00-00","circle_owner":"0","circle_owner_company":"26792","circle_company_identifier":"0","level":"OUTER","assign_fsm":"26792","assign_client":"25491","assign_am":"0","routine_1":"10065","routine_2":"10209","routine_3":"10062","routine_4":"0","image_duplicate_api":"Y","routine_1_type":null,"routine_1_method":null,"routine_1_cancel_buffer":null,"routine_2_type":null,"routine_2_method":null,"routine_2_cancel_buffer":null,"routine_3_type":null,"routine_3_method":null,"routine_3_cancel_buffer":null,"routine_4_type":null,"routine_4_method":null,"routine_4_cancel_buffer":null,"name":"FSM","added_datetime":"2014-02-12 16:16:51","clause":"fsm_company","can_issue":"2"},{"id":"1","company_id":"5","circle_id":"32","status":"A","cat_id":"1","company_map":"0","timestamp":"2015-07-09 15:28:40","added_by":"1","add_date":"0000-00-00","circle_name":"Cityside - HUD Contract Area - 2D","create_by":"2536","create_date":"0000-00-00","circle_owner":"0","circle_owner_company":"26792","circle_company_identifier":"0","level":"OUTER","assign_fsm":"26792","assign_client":"25491","assign_am":"0","routine_1":"10065","routine_2":"10209","routine_3":"0","routine_4":"0","image_duplicate_api":"Y","routine_1_type":null,"routine_1_method":null,"routine_1_cancel_buffer":null,"routine_2_type":null,"routine_2_method":null,"routine_2_cancel_buffer":null,"routine_3_type":null,"routine_3_method":null,"routine_3_cancel_buffer":null,"routine_4_type":null,"routine_4_method":null,"routine_4_cancel_buffer":null,"name":"FSM","added_datetime":"2014-02-12 16:16:51","clause":"fsm_company","can_issue":"1"}

编辑:

大家好,我试着分开回答。它似乎有所帮助,但在 3-4 个请求之后它仍然给我一个 OOM。我相信这与排球有关。这是我对每个响应的 GC,它每次都在增长。请注意,堆每次都会增长。我在它们之间放置了一些间距,以便您可以看到堆日志。

10-12 06:52:21.236 23515-23515/com.droid.visneta D/RequestQueue: batch_open_orders_request started...
10-12 06:52:21.236 23515-23855/com.droid.visneta D/GsonCustomHeaders: {UserSession=source=Android-ffffffff-83d1-3e36-ffff-ffff99d603a9,id=6,token=9eb7c26405defb48fe884cfef8000696}
10-12 06:52:21.236 23515-23855/com.droid.visneta I/qtaguid: Failed write_ctrl(t -1 4883184842671390720 -1) res=-1 errno=9
10-12 06:52:21.236 23515-23855/com.droid.visneta I/qtaguid: Tagging socket -1 with tag 43c48ebe00000000(1136955070) for uid -1 failed errno=-9
10-12 06:52:21.236 23515-23855/com.droid.visneta I/NetworkManagementSocketTagger: tagSocketFd(-1, 1136955070, -1) failed with errno-9
10-12 06:52:21.936 23515-23855/com.droid.visneta I/System.out: Removed SSLv3 from enabled protocols
10-12 06:52:21.976 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 1990K, 15% free 33771K/39495K, paused 11ms+1ms, total 38ms
10-12 06:52:29.940 23515-23855/com.droid.visneta I/qtaguid: Failed write_ctrl(u -1) res=-1 errno=9
10-12 06:52:29.940 23515-23855/com.droid.visneta I/qtaguid: Untagging socket -1 failed errno=-9
10-12 06:52:29.940 23515-23855/com.droid.visneta W/NetworkManagementSocketTagger: untagSocket(-1) failed with errno -9
10-12 06:52:31.808 23515-23855/com.droid.visneta D/dalvikvm: GC_FOR_ALLOC freed 747K, 14% free 34267K/39495K, paused 18ms, total 18ms
10-12 06:52:32.616 23515-23855/com.droid.visneta D/dalvikvm: GC_FOR_ALLOC freed 596K, 12% free 34778K/39495K, paused 21ms, total 21ms
10-12 06:52:32.616 23515-23855/com.droid.visneta I/dalvikvm-heap: Grow heap (frag case) to 36.423MB for 2093068-byte allocation
10-12 06:52:32.648 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 10K, 12% free 36811K/41543K, paused 10ms+1ms, total 29ms
10-12 06:52:32.648 23515-23855/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 9ms
10-12 06:52:33.272 23515-23855/com.droid.visneta D/dalvikvm: GC_FOR_ALLOC freed 1122K, 14% free 35790K/41543K, paused 20ms, total 20ms
10-12 06:52:33.272 23515-23855/com.droid.visneta D/Volley: [212] BasicNetwork.logSlowRequests: HTTP response for request=<[ ] <a href="https://dev.visneta.com/amf/gateway?contentType=application/json" rel="nofollow">https://dev.visneta.com/amf/gateway?contentType=application/json</a> 0x43c48ebe NORMAL 2> [lifetime=12039], [size=1652746], [rc=200], [retryCount=0]
10-12 06:52:33.296 23515-23855/com.droid.visneta D/dalvikvm: GC_FOR_ALLOC freed 2048K, 15% free 35360K/41543K, paused 22ms, total 22ms</p>

<p>10-12 06:52:33.296 23515-23855/com.droid.visneta I/dalvikvm-heap: Grow heap (frag case) to 38.149MB for 3305504-byte allocation</p>

<p>10-12 06:52:33.340 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 1K, 14% free 38586K/44807K, paused 11ms+11ms, total 43ms
10-12 06:52:33.392 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 555K, 11% free 40078K/44807K, paused 11ms+0ms, total 33ms
10-12 06:52:33.392 23515-23855/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 9ms
10-12 06:52:33.448 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 558K, 8% free 41568K/44807K, paused 11ms+1ms, total 36ms
10-12 06:52:33.448 23515-23855/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 15ms
10-12 06:52:33.504 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 564K, 4% free 43050K/44807K, paused 12ms+1ms, total 38ms
10-12 06:52:33.504 23515-23855/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 15ms
10-12 06:52:33.560 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 561K, 3% free 44537K/45575K, paused 10ms+1ms, total 38ms
10-12 06:52:33.560 23515-23855/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 8ms
10-12 06:52:33.616 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 577K, 3% free 46056K/47111K, paused 11ms+0ms, total 38ms
10-12 06:52:33.624 23515-23855/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 9ms
10-12 06:52:33.676 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 550K, 3% free 47555K/48583K, paused 11ms+1ms, total 38ms
10-12 06:52:33.676 23515-23855/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 16ms
10-12 06:52:33.764 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 4602K, 11% free 45006K/50119K, paused 11ms+12ms, total 58ms
10-12 06:52:33.840 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 2055K, 11% free 44998K/50119K, paused 10ms+0ms, total 45ms
10-12 06:52:33.840 23515-24293/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 26ms
10-12 06:52:33.916 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 2057K, 11% free 44988K/50119K, paused 11ms+1ms, total 43ms
10-12 06:52:33.916 23515-24293/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 21ms
10-12 06:52:33.988 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 2044K, 11% free 44991K/50119K, paused 11ms+1ms, total 41ms
10-12 06:52:33.988 23515-24293/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 21ms
10-12 06:52:34.056 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 2037K, 11% free 45002K/50119K, paused 11ms+1ms, total 41ms
10-12 06:52:34.060 23515-24293/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 8ms
10-12 06:52:34.132 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 2050K, 11% free 44995K/50119K, paused 11ms+0ms, total 42ms
10-12 06:52:34.132 23515-24293/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 8ms
10-12 06:52:34.216 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 2017K, 11% free 45026K/50119K, paused 11ms+11ms, total 53ms
10-12 06:52:34.216 23515-24293/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 2ms
10-12 06:52:34.284 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 2067K, 11% free 45004K/50119K, paused 11ms+0ms, total 40ms
10-12 06:52:34.288 23515-24293/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 23ms
10-12 06:52:34.372 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 2028K, 11% free 45000K/50119K, paused 11ms+12ms, total 54ms
10-12 06:52:34.452 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 2036K, 11% free 45012K/50119K, paused 12ms+1ms, total 48ms
10-12 06:52:34.452 23515-24293/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 4ms
10-12 06:52:34.524 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 2056K, 11% free 45003K/50119K, paused 12ms+0ms, total 41ms
10-12 06:52:34.524 23515-24293/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 22ms
10-12 06:52:34.596 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 2042K, 11% free 45004K/50119K, paused 11ms+1ms, total 43ms
10-12 06:52:34.600 23515-24293/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 18ms
10-12 06:52:34.668 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 2041K, 11% free 45009K/50119K, paused 11ms+1ms, total 42ms
10-12 06:52:34.668 23515-24293/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 21ms
10-12 06:52:34.744 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 2049K, 11% free 45007K/50119K, paused 11ms+1ms, total 41ms
10-12 06:52:34.744 23515-24293/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 19ms
10-12 06:52:34.776 23515-24293/com.droid.visneta D/BatchOpenOrders: 2000 open wos batched.
10-12 06:52:34.776 23515-23515/com.droid.visneta D/Routine Services Count: 1411
10-12 06:52:34.776 23515-23515/com.droid.visneta D/Open Order Count: 2000
10-12 06:52:37.288 23515-23515/com.droid.visneta D/RequestQueue: batch_open_orders_request started...
10-12 06:52:37.288 23515-23856/com.droid.visneta D/GsonCustomHeaders: {UserSession=source=Android-ffffffff-83d1-3e36-ffff-ffff99d603a9,id=6,token=9eb7c26405defb48fe884cfef8000696}
10-12 06:52:37.288 23515-23856/com.droid.visneta I/qtaguid: Failed write_ctrl(t -1 4883184842671390720 -1) res=-1 errno=9
10-12 06:52:37.288 23515-23856/com.droid.visneta I/qtaguid: Tagging socket -1 with tag 43c48ebe00000000(1136955070) for uid -1 failed errno=-9
10-12 06:52:37.288 23515-23856/com.droid.visneta I/NetworkManagementSocketTagger: tagSocketFd(-1, 1136955070, -1) failed with errno-9
10-12 06:52:37.592 23515-23856/com.droid.visneta I/System.out: Removed SSLv3 from enabled protocols
10-12 06:52:42.612 23515-23856/com.droid.visneta I/qtaguid: Failed write_ctrl(u -1) res=-1 errno=9
10-12 06:52:42.616 23515-23856/com.droid.visneta I/qtaguid: Untagging socket -1 failed errno=-9
10-12 06:52:42.616 23515-23856/com.droid.visneta W/NetworkManagementSocketTagger: untagSocket(-1) failed with errno -9
10-12 06:52:42.924 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 1779K, 10% free 45206K/50119K, paused 11ms+1ms, total 42ms
10-12 06:52:43.724 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 1104K, 9% free 46034K/50119K, paused 10ms+0ms, total 39ms
10-12 06:52:43.816 23515-23856/com.droid.visneta D/dalvikvm: GC_FOR_ALLOC freed 15K, 9% free 46033K/50119K, paused 28ms, total 28ms
10-12 06:52:43.816 23515-23856/com.droid.visneta I/dalvikvm-heap: Grow heap (frag case) to 47.417MB for 2095116-byte allocation
10-12 06:52:43.852 23515-23518/com.droid.visneta D/dalvikvm: GC_CONCURRENT freed 8K, 8% free 48071K/52167K, paused 12ms+1ms, total 38ms
10-12 06:52:43.852 23515-23856/com.droid.visneta D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 16ms
10-12 06:52:44.312 23515-23856/com.droid.visneta D/dalvikvm: GC_FOR_ALLOC freed 1108K, 10% free 47049K/52167K, paused 26ms, total 26ms
10-12 06:52:44.312 23515-23856/com.droid.visneta I/dalvikvm-heap: Grow heap (frag case) to 47.922MB for 1585235-byte allocation
10-12 06:52:44.340 23515-23856/com.droid.visneta D/dalvikvm: GC_FOR_ALLOC freed 0K, 10% free 48597K/53767K, paused 25ms, total 25ms
10-12 06:52:44.340 23515-23856/com.droid.visneta D/Volley: [213] BasicNetwork.logSlowRequests: HTTP response for request=<[ ] <a href="https://dev.visneta.com/amf/gateway?contentType=application/json" rel="nofollow">https://dev.visneta.com/amf/gateway?contentType=application/json</a> 0x43c48ebe NORMAL 3> [lifetime=7052], [size=1585223], [rc=200], [retryCount=0]
10-12 06:52:44.364 23515-23856/com.droid.visneta D/dalvikvm: GC_FOR_ALLOC freed 2050K, 14% free 46551K/53767K, paused 26ms, total 26ms</p>

<p>10-12 06:52:44.368 23515-23856/com.droid.visneta I/dalvikvm-heap: Grow heap (frag case) to 48.949MB for 3170458-byte allocation</p>

问题不在于 Volley 或 Retrofit,它很可能与大小或数据响应有关。如果您可以控制网络服务,您应该考虑使用分页将信息分解成更小的块。

响应非常大(超过 5 Mb),弱设备没有足够的 RAM 是有道理的。这是一项艰巨的工作,但如果服务器端由您管理,您应该将此响应拆分为几个响应。以块的形式发送它是行不通的,因为在处理响应之前您仍然必须将它们拼凑在一起,而且无论如何我认为您不应该在一个请求中解析这么多数据。

我也建议你看看这个答案,它会帮助你找到你检查的设备的限制:。

如果您可以控制服务器端,IMO,响应数据压缩是解决此类问题的另一种方法。 当然,在客户端,你必须先解压网络响应,然后再正常解析。

如果您的服务器应用程序是 ASP.NET Web API, for example, you can take a look at this ASP.NET Web API Compression 文档以供参考。我认为其他网络服务或某些网络服务器也支持压缩。

希望对您有所帮助!

好吧,我对 volley 了解不多,但我用 Jackson lib 处理过这种 json 响应。

检查这个答案Android: Parsing large JSON file

我认为 Jackson stream API 是正确的选择。