我需要從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