我需要从SQLite数据库中读取大量数据并创建格式正确的JSON。Android巨大的JSONObject toString去OutOfMemoryError
我目前通过一个名为RequestPayload
的对象来实现这个功能,其中包含一些ArrayList
s,其中我从SQLite中读取数据。
的RequestPayload
类有一个parseJson()
方法返回一个JSONObject
上,我最终调用toString()
方法来获取最终得到了书面上的文件我的JSON字符串。
现在,当我在SQLite中获得“少量”数据时,一切都很顺利。当我有大量的数据,这是发生了什么:
06-28 09:55:34.121 10857-6799/it.example.sampler E/AndroidRuntime: FATAL EXCEPTION: Thread-195240
Process: it.example.sampler, PID: 10857
Theme: themes:{com.cyanogenmod.trebuchet=overlay:system, com.android.settings=overlay:system, default=overlay:system, iconPack:system, fontPkg:system, com.android.systemui=overlay:system, com.android.systemui.navbar=overlay:system}
java.lang.OutOfMemoryError: Failed to allocate a 52962812 byte allocation with 16764752 free bytes and 41MB until OOM
at java.lang.StringFactory.newStringFromChars(Native Method)
at java.lang.AbstractStringBuilder.toString(AbstractStringBuilder.java:629)
at java.lang.StringBuilder.toString(StringBuilder.java:663)
at org.json.JSONStringer.toString(JSONStringer.java:430)
at org.json.JSONObject.toString(JSONObject.java:690)
at it.example.sampler.controllers.network.RequestBodyEncoder.serialise(RequestBodyEncoder.java:69)
at it.example.sampler.controllers.network.RequestBodyEncoder.createPacket(RequestBodyEncoder.java:50)
at it.example.sampler.services.FileStoreRunnable.run(FileStoreRunnable.java:57)
at java.lang.Thread.run(Thread.java:818)
06-28 09:55:34.509 10857-10857/it.example.sampler E/WindowManager: android.view.WindowLeaked: Activity it.example.sampler.ui.StartSamplingActivity has leaked window com.android.internal.policy.PhoneWindow$DecorView{74710d V.E...... R......D 0,0-1026,494} that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:372)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:299)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:86)
at android.app.Dialog.show(Dialog.java:319)
at it.example.sampler.ui.StartSamplingActivity.executeStop(StartSamplingActivity.java:305)
at it.example.sampler.ui.StartSamplingActivity.onClickedButton(StartSamplingActivity.java:256)
at it.example.sampler.ui.StartSamplingActivity$3.onClick(StartSamplingActivity.java:190)
at android.view.View.performClick(View.java:5204)
at android.view.View$PerformClick.run(View.java:21158)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5461)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
现在代码:
错误行是从这个方法:
private String serialise() throws JSONException {
// Serialise
String sampleString = mPayload.parseJSON().toString(); // THIS LINE
Logger.get().d(LOG_TAG, "Serialised payload: -> " + sampleString);
return sampleString;
}
,如果我得到了logcat的正确的错误是在执行toString()
方法的过程中,看起来JSON对象太大了。
我该如何处理这种情况?
更新: 回答@YashJain评论询问JSONObject的大小。
采样的采样之后历时2小时,我不得不含有JSON:
- JSONArray含有155.432
float
小号 - JSONArray含有8.393含有
float
小号 - JSONArray 8.393自定义对象每个包含5个
float
(和一个字符串) 含有
- 2D阵列155.432
int
小号
在字节方面由于浮子是由4个字节(希望我已经做正确的演算)我有大约制成:
(12 * 155432 * 4) + (2 * 8393 * 4) + (1 * 8393 * 5) + (1 * 155432 * 4) ~= 8.191.573 bytes
更新: 我被问到有关使用的压缩算法。我通过Deflater
和DeflaterOutputStream
Java类使用ZLIB
。
这样的流程是:
- 样品数据 - >将它们储存在
SQLite
- 读自
SQLite
- >构建RequestPayload
对象在内存 - 转换
RequestPayload
对象JSONObject
(自定义自定义解析器)。 - 转换的
JSONObject
到字符串(使用JSONObject
toString()
方法) - 压缩字符串字节(使用
getBytes()
) - >对其进行编码以Base64 - 发送最终的Base64串到服务器
编辑: 为了回应“可能重复的旗帜”,我没有看到这个问题在我的研究过程中没有帮助我,因为它使用了largeHeap
指令(我没有使用)。也没有公认的答案,唯一的答案实际上并没有提供一个实际的解决方案。
[JSONObject.toString()可能重复返回OutOfMemoryError]( http://stackoverflow.com/questions/32919833/jsonobject-tostring-returns-outofmemoryerror) – mdDroid
我不知道答案,但我想知道它能够容纳多大的数据?像多少字节/字符一样。 –
@mdDroid我已经添加了一个编辑,解释为什么我没有“可能重复”标志可能会有所帮助..无论如何谢谢标记,因为我没有看到它在研究之前问这个问题..可悲它没有帮助 – FredMaggiowski