У меня есть действие, которое я получаю большой список объектов, около 25 000 объектов, содержащих в общей сложности около 600 000 строк, это занимает около 20 МБ кучи. Этот список загружается в adapter
для recyclerview
, который затем отображает список.
Моя проблема заключается в том, что когда я закрываю действие, и действие предположительно «уничтожается», огромный список объектов не мусор собрал. Поэтому моя куча по-прежнему содержит 20 МБ объектов, и когда я снова открываю это действие, в него добавляется еще 20 МБ объектов, и память быстро израсходуется.
В методе действия onDestroy()
я попытка освободить ссылку на adapter
, которая содержит огромный список объектов. Я также выпускаю ссылку на recyclerView
и viewModel
, viewModel - это место, где я получаю слова из объекта LiveData
, который обновляет adapter
.
@Override
protected void onDestroy() {
adapter = null;
recyclerView = null;
viewModel = null;
Log.d("kesD", "onDestroy: pls free up my MB");
super.onDestroy();
}
Хотя это не работает, и кажется, что 20MB объектов не удаляются из кучи, как показано в этом выводе консоли ниже:
(акцент на 57 МБ / 81 МБ , показанные до и после уничтожения действия и освобождения объектов)
2020-02-05 20:18:36.349 2042-2077/co.uk.SpeedSpanish I/uk.SpeedSpanis: Background concurrent copying GC freed 461591(31MB) AllocSpace objects, 6(312KB) LOS objects, 29% free, 57MB/81MB, paused 151us total 238.203ms
2020-02-05 20:18:36.443 2042-2042/co.uk.SpeedSpanish D/kesD: onDestroy: pls free up my MB
2020-02-05 20:18:37.198 2042-2077/co.uk.SpeedSpanish I/uk.SpeedSpanis: Background concurrent copying GC freed 445259(31MB) AllocSpace objects, 0(0B) LOS objects, 29% free, 56MB/80MB, paused 98us total 240.906ms
Я удостоверился, что нет никаких ссылок c на активность, которая может поддерживать его (и мой список объектов) живым.
Список объектов нигде не упоминается статически, но я фильтрую список с помощью метода stati c в другом потоке как показано ниже:
private void getViewModelAllWords(){
viewModel = ViewModelProviders.of(this).get(WordViewModel.class);
adapter = new WordDetailedAdapter(this, viewModel, this, this, false);
viewModel.getAllWordsLive().observe(this,words -> {
Collections.sort(words, (o1, o2) -> o1.getWord().compareToIgnoreCase(o2.getWord()));
filterWords(words);
});
}
private void filterWords(List<Word> words) {
FilterThread thread = new FilterThread(words);
thread.start();
}
private class FilterThread extends Thread{
private List<Word> allWords;
public FilterThread(List<Word> allWords){
this.allWords = allWords;
}
@Override
public void run() {
if(allWords!=null){
final List<Word> words = WordFilter.getFilteredList(allWords, wordClassStr, wordCategoryStr);
runOnUiThread(() -> applyFilteredWords(words));
allWords = null;
}
}
}
private void applyFilteredWords(List<Word> words){
adapter.submitList(words);
}
@Query("SELECT * FROM Word ORDER BY word")
LiveData<List<Word>> getAllWordsLive();
Я также освобождаю ссылку на список после фильтрации, так что это не должно быть проблематичным c.