Я пишу приложение для Android. Из-за цели я должен (вставить) кэшировать свой список пользователей размером 10 МБ в sqlite db. Когда пользователь запускает вызов API, я отправляю поток ввода в BufferedReader и использую char[] buffer = new char[2048];
в качестве фрагмента, потому что, если я читаю поток ввода построчно, сценарий не продолжается (я думаю, что это приводит к тому, что из моего тела 10 МБ получается одна строка, и она слишком велика для чтения) . Когда это происходит, использование моей памяти увеличивается до 90 МБ со стабильных 10 МБ. код ниже
private String getResult() {
String Result = "";
try {
....
StringBuilder stringBuilder = new StringBuilder();
int HttpResult = connection.getResponseCode();
if (HttpResult == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), CharsetNames.Utf8.value));
String line = null;
char[] buffer = new char[2048];
int count;
while ((count = reader.read(buffer)) != -1) {
String s = new String(buffer, 0, count);
stringBuilder.append(s);
}
reader.close();
Result = stringBuilder.toString();
} else {
Result = null;
}
} catch (InterruptedIOException e) {
} catch (IOException e) {
e.printStackTrace();
Tools.ShowStandartErrorToast();
}
return Result;
}
1_ почему, когда я красный 10 МБ тела от apicall, почему использование памяти моего приложения (java) увеличивается на 80 МБ вместо 10 МБ и решение?
После того, как этот метод возвращает строковый результат, я использую его для инициализации объекта json. И затем я использую этот json для инициализации своих экземпляров объектов. После этой операции использование памяти уменьшается до 320 мб.
protected Result doInBackground(Parameter Parameter) {
...........
ApiHelper = new ApiHelper(getSelectedService(), parameter.getAsJson());
String resultString = ApiHelper.getResult();
result = setResult(resultString);
...........
}
public class UserListResponse extends BaseResponse {
public static final String UserList_FIELD_NAME = "UserList";
public List<User> UserList;
public UserListResponse(String baseStringResult) {
try {
this.baseJsonResult = new JSONObject(baseStringResult);
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
this.baseJsonResult = new JSONObject();
}
}
@Override
protected void mapFields() {
if (baseJsonResult.has(UserList_FIELD_NAME) && !baseJsonResult.isNull(UserList_FIELD_NAME)) {
try {
JSONArray jaPerson = baseJsonResult.getJSONArray(UserList_FIELD_NAME);
UserList = new ArrayList<>(jaPerson.length());
for (int i = 0; i < jaPerson.length(); i++) {
JSONObject joPersonInfo = jaPerson.getJSONObject(i);
User pi = new User();
pi.init(joPersonInfo);
UserList.add(pi);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
2_ Если причина в том, что я в основном использую строковые поля, как я могу освободить эти строковые поля. Я думаю, что они продолжают жить, даже если я объявляю их методом.
Я использовал System.gc() везде, где это было возможно, но это не повлияло на использование памяти.
stringBuilder
займет 20 МБ, а затемResult
еще 20 МБ ... также выделениеs
на каждой итерации также займет в совокупности 20 МБ ... для 10 МБ JSON, очевидно, было бы лучше использовать какой-нибудь потоковый синтаксический анализатор JSON - person Selvin   schedule 18.07.2018