The RecyclerView library recently added the new SortedList
class. Suppose I have a callback that implements a compare()
method that can change over time, i.e. the underlying Comparator can be switched out. What's the best way to tell the SortedList
to completely resort its data?
Like other adapterviews, recyclerviews need adapter. It is the adapter that maintains the data source on behalf of recyclerview. Given the large use scenarios of recyclerviews, it makes sense to be able to sort them. Example 1: Kotlin Android – RecyclerView Sort Ascending/Descending
RecyclerView RecyclerView is a list component that allows us render large data sets efficiently. These days it is the most commonly used adapterview. This courtesy of it’s felxibility, power and ease of use. Like other adapterviews, recyclerviews need adapter. It is the adapter that maintains the data source on behalf of recyclerview.
You can see you declare recyclerview using the android.support.v7.widget.RecyclerViewclass. Then we’ve assigned it an id which will be used to identify it. (b). model.xml
Introduction to SortedList Android SDK provides a class called SortedList that provides us an easy way to sort data. SortedList is able to respect the order of items added to it and notify of changes to that order. It was added in android version 22.1.0 and belongs to the android.support.v7.utilpackage.
Here's my own take on it (written in Kotlin):
list.beginBatchedUpdates()
val indices = (0..list.size() - 1).toArrayList()
while (!indices.isEmpty()) {
val i = indices.first()
val item = list.get(i)
list.recalculatePositionOfItemAt(i)
[suppress("USELESS_CAST_STATIC_ASSERT_IS_FINE")]
indices.remove(list.indexOf(item) as Any) //cast to disambiguate remove()
}
list.endBatchedUpdates()
As you can see, I'm tracking the new index after every call to recalculatePositionOfItemAt()
so every item is resorted only once and no item is skipped.
This works but seems really wasteful because recalculatePositionOfItemAt()
will resize the underlying array twice to remove and then readd the item. indexOf
will then perform a new binary search even though the index is already known.
Edit: This seems to lead to an infinite loop if items compare as equal.
Alternative approach (remove all, then add all):
list.beginBatchedUpdates()
val copy = (list.size() - 1 downTo 0).map { list.removeItemAt(it) }
copy.forEach { list.add(it) }
list.endBatchedUpdates()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With