Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to completely resort RecyclerView's SortedList

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 image 912
Kirill Rakhman Avatar asked Apr 22 '15 12:04

Kirill Rakhman


People also ask

Can recyclerviews sort?

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

What is recyclerview in Salesforce?

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.

How to declare a recyclerview in Android?

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

What is sortedlist in Android?

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.


1 Answers

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()
like image 194
Kirill Rakhman Avatar answered Oct 12 '22 23:10

Kirill Rakhman