android - androidx.RecyclerView ListAdapter 很慢
问题描述
我正在使用ListAdapter
RecyclerView 并且在某些情况下应用程序变得非常慢 - 它冻结了 10 秒,并列出了 1000 个项目。
情况是,首先我提交了一个包含 1000 个项目的列表(首先按预期快速提交),然后我再次提交相同的列表,但排序不同。
通过大量调试,我终于发现, ListAdapter 触发了 a notifyItemRangeChanged(0, 999)
,所以基本上是完整的列表。我在其他地方(这里和这里)读到,不应该这样做,因为它会使 RecyclerView 变慢——这显然是正确的——但是,我不能影响 ListAdapter 的行为。
有没有人有解决方案?我不想再次删除 ListAdapter,因为对于大多数其他用例来说,它既快速又方便,可以自动执行各种动画等。
编辑 - 一些代码
代码没什么花哨的,基本上是这样的:
RecyclerView mListView;
EnryListAdapter mEntryListAdapter; // <-- extends ListAdapter<Entry, VH>
...
mEntryListAdapter = new EntryListAdapter();
mListView.setAdapter(mEntryListAdapter);
mListView.setLayoutManager(new LinearLayoutManager(this));
mListView.setHasFixedSize(true);
((DefaultItemAnimator) mListView.getItemAnimator()).setSupportsChangeAnimations(false);
List<Entry> entryList = getEntryList(); // <-- list with 1000 entries
mEntryListAdapter.submitList(entryList); // <-- first submit is fast
entryList = getDifferentlySortedEntryList(); // <-- list with same entries, sorted differently
mEntryListAdapter.submitList(entryList); // <-- freezes app for over 10 seconds
解决方案
最后,我发现这是我自己的错误。
在我的实施中,DiffUtil.ItemCallback<Entry>#areContentsTheSame
我进行了以下检查:
oldItem.flags == newItem.flags
whereEntry.flags
是long
第一个,但后来我将其更改为 class 的实例,而没有更改此比较。由于实例不是相同的对象,因此这种比较false
一直都会产生。将其替换为
ObjectsCompat.equals(oldItem.flags, newItem.flags)
解决了这个问题。
推荐阅读
- sql - 雪花:“SQL 编译错误:...不是有效的按表达式分组”
- google-app-engine - 批量排队 Google Cloud 任务
- matlab - Matlab图形多个光标条
- javascript - 在 NW.js 应用程序中使用时,Windows 上的 drivelist 错误(动态链接库 (DLL) 初始化例程失败)
- python - 向 Dash-Plotly Python 仪表板添加水平线
- javascript - 需要帮助重构代码以解决 eslint 无循环警告
- html - 正则表达式数字模式和 maxlength 在 IE 上不起作用
- python - MySQL - 如果表名包含表列表的记录,则选择表名
- java - Java秒表类
- matlab - 如何最好地实现与 Matlab 的 intersect 函数等效的 Fortran