I am using the ListAdapter
with RecyclerView and under certain circumstances the app becomes extremely slow -- it freezes for 10 seconds with a list of 1000 items.
The circumstances are, that at first I submit a list with 1000 items (at first submit its fast as expected) and then I submit the same list again, but sorted differently.
By debugging a lot, I finally found out, that the ListAdapter triggers a notifyItemRangeChanged(0, 999)
, so basically for the complete list. I read elsewhere (here and here), that one should not do this, because it makes the RecyclerView slow -- which apparently is true -- however, I cannot influence the behaviour of the ListAdapter.
Does anyone have a solution for that? I don't want to remove ListAdapter again, because for most other usecases it is fast and handy, doing various animations etc. automatically.
EDIT - some code
There is nothing fancy about the code, basically it's like that:
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
In the end, I found out that it was my own mistake.
In my implementation of DiffUtil.ItemCallback<Entry>#areContentsTheSame
I had this check:
oldItem.flags == newItem.flags
where Entry.flags
was a long
first, but later on I changed it to be an instance of a class, without changing this comparison. Since the instances aren't the same objects, this comparison then resulted in false
all the time. Replacing it with
ObjectsCompat.equals(oldItem.flags, newItem.flags)
fixed the issue.