【发布时间】:2020-05-21 20:38:21
【问题描述】:
我有一个活动,我获得了大量对象,大约 25,000 个对象,总共包含大约 600,000 个字符串,这占用了大约 20MB 的堆。此列表被加载到 adapter 中,recyclerview 然后显示列表。
我的问题是,当我关闭活动并且活动被“销毁”时,庞大的对象列表不会被垃圾收集。因此,我的堆仍然包含 20MB 的对象,当我重新打开该活动时,另外 20MB 的对象被添加到堆中,并且内存很快被耗尽。
在活动的onDestroy() 方法中,我尝试释放对包含大量对象列表的adapter 的引用。我还发布了对recyclerView 和viewModel 的引用,viewModel 是我从更新adapter 的LiveData 对象获取单词的地方。
@Override
protected void onDestroy() {
adapter = null;
recyclerView = null;
viewModel = null;
Log.d("kesD", "onDestroy: pls free up my MB");
super.onDestroy();
}
虽然这不起作用,并且似乎没有从堆中删除 20MB 的对象,如下面的控制台输出所示:
(强调57MB/81MB之前显示的和销毁活动并释放对象之后)
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
我已确保没有对可能使其(以及我的对象列表)保持活动状态的活动的静态引用。
对象列表在任何地方都没有被静态引用,但我确实使用不同线程中的静态方法过滤列表,如下所示:
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();
我也在过滤后释放对列表的引用,所以这应该没有问题。
【问题讨论】:
-
这听起来像是Dump Java heap 的工作。
-
请说明您是如何加载列表的
-
@LenaBru 我添加了更多代码来演示列表的来源。
-
getAllWordsLive()是如何获得的?
-
@LenaBru 它是一个 LiveData
- > 对象,它使用
SELECT *SQL 语句从我的 Room 数据库中获取列表。
标签: java android performance memory