我收到以下 OutOfMemoryError 例外嘗試翻閱來自 API 的回應
引起:java.lang.OutOfMemoryError:無法分配 37748744 位元組的分配,其中有 25165824 個空閑位元組和 24MB,直到 OOM,目標占用空間 268261936,在 java.util.Arrays.copyOf(Arrays.java:3257) 的增長限制 268435456 lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:649) at java.lang.StringBuilder.append(StringBuilder.java:203) at com.richmondgamesstudio.inattaxonomytreeviewer.utils .INatCall.readAll(INatCall.java:105) 在 com.richmondgamesstudio.inattaxonomytreeviewer.utils.INatCall.restCalliNat(INatCall.java:56) 在 com.richmondgamesstudio.inattaxonomytreeviewer.utils.INatCall.restCalliNat(75). com.richmondgamesstudio.inattaxonomytreeviewer.utils.INatCall.restCalliNat(INatCall.java:75) 在 com.richmondgamesstudio。inattaxonomytreeviewer.utils.INatCall.restCalliNat(INatCall.java:75) 在 com.richmondgamesstudio.inattaxonomytreeviewer.utils.INatCall.doInBackground(INatCall.java:42)
有沒有更有效的方法來通過休息處理大量資料?我的應用程式呼叫回傳用戶“條目”的 API。API 的最大頁數為 200。大多數用戶將擁有 200 多個條目,這在大多數情況下都很好。我的應用程式可以對此進行分頁和說明。但是,有些用戶將擁有 2000 個條目,而我的應用程式在嘗試遍歷這些較大的集合時記憶體不足。我的問題是:
- 有沒有辦法增加我的 android 應用程式可以使用的記憶體量?
- 有哪些方法可以優化以下代碼以使用更少的記憶體?
遞回休息呼叫
private JSONArray restCall(URL url, JSONArray results) {
Log.d(TAG, "restCalliNat: Start");
InputStream is = null;
int totalResults = 0;
int perPage = 0;
JSONArray newResults = new JSONArray();
try {
is = url.openStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd); //<-- LINE 56
is.close();
rd.close();
JSONObject json = new JSONObject(jsonText);
newResults = json.getJSONArray("results");
totalResults = (int) json.get("total_results");
perPage = (int) json.get("per_page");
} catch (IOException | JSONException e) {
e.printStackTrace();
return null;
}
if (results != null) {
newResults = concatArray(results, newResults);
}
if (totalResults > page*perPage) {
newResults = restCall(updatePageCount(url), newResults);
}
return newResults;
}
在每個新頁面上,新頁面都會連接起來,直到我擁有所有條目。
private JSONArray concatArray(JSONArray arr1, JSONArray arr2) {
JSONArray result = new JSONArray();
try {
for (int i = 0; i < arr1.length(); i ) {
result.put(arr1.get(i));
}
for (int i = 0; i < arr2.length(); i ) {
result.put(arr2.get(i));
}
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
將 API 回應轉換為字串
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp); //<--- LINE 105
}
return sb.toString();
}
uj5u.com熱心網友回復:
我的應用程式記憶體不足
這不完全是錯誤所說的:Caused by: java.lang.OutOfMemoryError: Failed to allocate a 37748744 byte allocation with 25165824 free bytes and 24MB until OOM。您有 24MB 的可用記憶體。但是,您正在嘗試分配 36MB 的單個緩沖區,這是行不通的。即使您有 124MB 或 524MB 的空閑記憶體,您也可能無法訪問單個 36MB 的連續空閑記憶體塊。
將 API 回應轉換為字串
任何一個:
- 一次從您的 REST Web 服務請求更少的專案(而不是 200,嘗試 5);或者
- 停止嘗試將整個 API 回應讀入字串,因為您的 API 回應非常大
您可能想嘗試使用更現代的解決方案來訪問 REST 風格的 Web 服務。例如,Retrofit非常流行,不需要您將整個原始 JSON 讀入單個字串。即使您想堅持使用openStream()-on-a-URL方法,現代 JSON 決議器(Moshi、Gson,甚至JsonReaderAndroid SDK 中的)都是流式決議器,并且不需要您將整個原始 JSON 讀入單個字串。
uj5u.com熱心網友回復:
事實證明,我正在呼叫的權限對您可以請求的頁面數量有限制。
per_Page 計數限制為頁面的 200 個結果。但是 page_count 限制是 page * per_Page > 1000。所以 per_page 計數是多少并不重要。如果頁面 * per_Page > 1000 比它會取消呼叫。即使在一條小溪中間。
uj5u.com熱心網友回復:
在您的清單中添加android:hardwareAccelerated="false",android:largeHeap="true"它適用于某些情況,
<application
android:allowBackup="true"
android:hardwareAccelerated="false"
android:largeHeap="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/359676.html
