Пиша приложение за android. Заради целта трябва да (вмъкна) кеш моя потребителски списък с размер 10 mb в sqlite db. Когато потребителското задейства api извикване, изпращам входния поток до BufferedReader и използвам char[] buffer = new char[2048];
като парче, защото ако чета входен поток ред по ред, скриптът не продължава (мисля, че това причинява от моето 10mb тяло е един ред и е твърде голямо за четене) . Когато това се случи, използването на паметта ми се увеличава до 90mb от 10mb стабилно. кодът е по-долу
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 mb тяло от apicall, защо използването на паметта на моето приложение (java) се увеличава с 80 mb вместо с 10 mb и решението?
След като този метод върне резултат от низ, аз го използвам за инициализиране на json обект. И след това използвам този json, за да инициализирам моите екземпляри на обекти. След тази операция използването на паметта намалява до 320 mb.
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
ще отнеме 20MB и след товаResult
още 20MB ... също разпределението наs
във всяка итерация също ще отнеме кумулативно 20MB ... за 10MB JSON очевидно би било по-добре да използвате някакъв анализатор на поток JSON - person Selvin   schedule 18.07.2018