Я создаю приложение, которое включает чтение данных из файла. Файл относительно большой (1,8 МБ) и считывается из асинхронного потока в onCreate. В первый раз, когда приложение запущено, оно загружается просто отлично. Однако, если вы нажмете кнопку "Назад", а затем загрузите ее снова, у нее закончится нехватка памяти и сбои (выброс ошибки OutOfMemory).
Как мне заставить его использовать наименьший объем памяти и/или освобождать эту память, когда это будет сделано?
Код чтения файлов (выполнен в методе doInBackground()
класса async):
public ArrayList<String> createDataList() {
dataList = new ArrayList<String>();
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(getAssets().open(
"text.txt")));
String data;
while ((data = br.readLine()) != null) {
dataList.add(data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close(); // stop reading
} catch (IOException ex) {
ex.printStackTrace();
}
}
return dataList;
}
ИЗМЕНИТЬ * Класс Async:
private class loadData extends AsyncTask<Void, Void, ArrayList<String>> {
@Override
protected ArrayList<String> doInBackground(Void... arg0) {
dataList = createDataList();
return dataList;
}
protected void onPostExecute(ArrayList<String> result) {
super.onPostExecute(result);
// display first element in ArrayList in TextView as a test
}
}
Я попытался разбить файл на основе того, как я хочу организовать данные и хранить данные из каждого текстового файла в отдельный ArrayList
, но у меня также были проблемы с памятью. Я также сохранил все данные в один "мастер" ArrayList
, а затем вызвал метод на этом "хозяине", чтобы добавить данные в соответствующий ArrayList
(удаление/очистка данных от "мастера", как только он копируется).
Любые идеи о том, как оптимизировать и уменьшить влияние памяти?
ИЗМЕНИТЬ **
Logcat:
То есть, когда вы нажимаете кнопку "Назад", а затем снова загружаете действие. Ниже приведено только одно из сообщений (в подробностях):
Во-первых, убедитесь, что у вас нет двух копий данных в памяти. Вы можете исключить ссылку на старый ArrayList, прежде чем приступать к созданию нового, хотя вы должны сделать это осторожно: сначала вызов ArrayList.clear()
будет более тщательным.
Во-вторых, выясните, сколько памяти ArrayList съедает с помощью инструмента, такого как hprof
или Eclipse MAT. Если он использует тонну пространства, вы можете рассмотреть более компактное представление данных.
Итак... из фрагмента кода, похоже, вы просто читаете кучу текстовых строк из файла, используя преобразование byte-to- char. Если исходный материал является простым UTF-8 (то есть, по существу, ASCII), у вас есть расширение 2x для UTF-16, а также выделение объекта char [] для его хранения, а также размер объекта String, который обертывает что плюс накладные расходы на запись в ArrayList. В зависимости от того, как долго средняя строка в файле, это может быть значительным числом на вашем 1.8MB.
Один из способов избежать этого - прочитать файл в памяти как byte[]
, отсканировать его, чтобы выяснить, где начинается каждая строка, и просто сохранить массив целых чисел со стартовым смещением каждой строки. Когда вам понадобится строка N, декодируйте ее с byte[]
в String
и верните ее. Это значительно снижает ваши накладные расходы. Вы можете уменьшить его, не загружая файл и просто считывая отдельные строки при необходимости (используя RandomAccessFile
), но это может замедлить работу.
Кажется, у вас могут быть проблемы с неизменностью строк.
Почему бы вам не попробовать изменить код, чтобы использовать StringBuilder? Конечно, вам придется изменить несколько вещей, но это будет достаточно похоже на ваш код и не будет заполнять вашу память так же быстро.
Вы можете попробовать добавить android:largeHeap="true"
в манифест, но он не поддерживается в Android API-8. Насколько я понимаю, вы читаете и храните данные в кучевую память, которая обычно довольно ограничена, и ее размер зависит от устройства, на котором работает ваше приложение.
Вы также можете изучить здесь: android - из памяти
dataList.add();
заявления, чтобы избежать чтения из файла. Однако это не кажется очень практичным, и я не хочу этого делать, если я могу избежать этого.