Android 处理大型 JSON 响应时出现 OutOfMemoryException

Android OutOfMemoryException when processing large JSON response

我在处理非常长的 JSON 响应时收到 OutOfMemoryException 由以下代码返回:

HttpClient httpclient = new DefaultHttpClient();
HttpGet httpGETRequest = new HttpGet(url);
HttpResponse response = httpclient.execute(httpGETRequest);
return EntityUtils.toString(response.getEntity());  

即使我在调用http请求之前使用System.gc(),仍然会出现异常。

我试图通过将响应保存在记事本上并检查其大小来查找问题的原因,结果发现它是一个 5mb 的文件。

为了避免异常应该做些什么?

提前感谢您的帮助。

我不建议您在 Android 上使用 System.gc()。您需要做的是使用流式传输,如果可以避免,则避免将整个内容加载到内存中。

https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/JsonStreamParser.html

如果您需要更轻松地访问部分 JSON 数据而不是一次访问一个块,您可以在读取数据时转换数据并将其存储在 SQL 以后可以查询的数据库。

http://developer.android.com/training/basics/data-storage/databases.html

但是,如果您嵌入了二进制数据(例如图像)作为 JSON 对象的一部分,您将无法再对它做任何事情,因为它会将嵌入的二进制数据作为一个块读入内存。除了编写您自己的 JSON 流媒体之外,没有简单的解决方法。

一般

这种通用技术不仅可以应用于 Android,甚至可以应用于处理大量输入数据的应用程序服务器,例如 XML。

调用 System.GC() 不保证 运行 GC。事实上,以编程方式调用 GC 并不是一个好习惯。要解析大型 json 数据,请在您用于 encode/decode json 的任何库中使用流式 API。 Jackson 处理器就是这样一种流行的库。

5mb不是大数据导致内存不足,可能会转储应用程序的内存并分析内存泄漏。你可以使用 adb dumpsys sump 工具。在 What's the Android ADB shell "dumpsys" tool and what are its benefits?

中查找有关如何使用它的更多信息
try {
        HttpResponse response = httpclient.execute(httppost);
        HttpEntity entity = response.getEntity();
        inputStream = entity.getContent();
        // json is UTF-8 by default
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        result = sb.toString();
        inputStream.close();
    } catch (Exception e) {
        Log.d(TAG, "String was to large" + e.toString());
    }

我认为如果你在将 5Mb 字符串加载到内存中时遇到问题(完全合理的大小),流式 JSON 解析器可能无济于事,因为你需要在内存中解析结果,这不会一定要小得多。我建议您使用 Android Studio 内置内存监视器进行内存分析,以检查您有多少可用内存以及您通常如何使用它。

在这种情况下,我们应该避免来自服务器的大数据响应。我从服务器请求了分页功能,问题解决了。