Android: SortedList with duplicates

后端 未结 6 913
栀梦
栀梦 2021-02-19 21:58

I have some problems understanding RecyclerViews SortedList.

Lets say I have a very simple class only having a very simple class holding data:<

6条回答
  •  佛祖请我去吃肉
    2021-02-19 22:00

    I had a similar issue when creating a chat app which I need to update messages by their IDs and sort them by their dates. The support lib's SortedList does not do that or at least I had little time to dive into its source code and test. So, I created a small component, MultiSortedList:

    import android.support.v7.widget.RecyclerView
    
    /**
     * Created by abduaziz on 6/14/18.
     *
     *   MultiSortedList is a wrapper component to ArrayList that keeps its elements in a sorted order
     *   using UpdateCallbackInterface. It is intended to be used inside recycler view adapters.
     *
     * */
    
    class MultiSortedList(var updateCallback: UpdateCallback, var adapter: RecyclerView.Adapter<*>? = null) {
    
        companion object {
            val TAG = "SORTEDLIST"
        }
    
        // internal list to hold elements by sortBy() -> visible to user
        private val list: ArrayList = arrayListOf()
    
        // internal list to hold elements by updateBy() -> not visible
        private val uList: ArrayList = arrayListOf()
    
        // add adapter from ui
        fun addAdapter(adapter: RecyclerView.Adapter<*>?) {
            this.adapter = adapter
        }
    
        /*
        * 1. Search for existing element that satisfies updateBy()
        * 2. Remove the existing element if found
        * 3. Add the new item with sortBy()
        * 4. Notify if adapter is not null
        * */
        fun add(newItem: T) {
            remove(newItem)
    
            // save to internal list by updateBy()
            var toBeStoredPosition = uList.binarySearch { updateCallback.updateBy(it, newItem) }
            if (toBeStoredPosition < 0) toBeStoredPosition = -(toBeStoredPosition + 1)
            uList.add(toBeStoredPosition, newItem)
    
            // save to UI list and notify changes
            var sortPosition = list.binarySearch { updateCallback.sortBy(it, newItem) }
            if (sortPosition < 0) sortPosition = -(sortPosition + 1)
            list.add(sortPosition, newItem)
            adapter?.notifyItemInserted(sortPosition)
        }
    
        /*
        * Remove and notify the adapter
        * */
        fun remove(removeItem: T) {
            val storedElementPosition = uList.binarySearch { updateCallback.updateBy(it, removeItem) }
            if (storedElementPosition >= 0 && storedElementPosition < uList.size) {
    
                // remove from internal list
                val itemTobeRemoved = uList[storedElementPosition]
                uList.removeAt(storedElementPosition)
    
                // remove from ui
                val removePosition = list.binarySearch { updateCallback.sortBy(it, itemTobeRemoved) }
                if (removePosition >= 0 && removePosition < list.size) {
                    list.removeAt(removePosition)
                    adapter?.notifyItemRemoved(removePosition)
                }
            }
        }
    
        // can be accessed -> list.get(position) or list[position]
        operator fun get(pos: Int): T {
            return list[pos]
        }
    
        // for adapter use
        fun size(): Int {
            return list.size
        }
    
        inline fun forEachIndexed(action: (Int, T) -> Unit) {
            for (index in 0 until size()) {
                action(index, get(index))
            }
        }
    
        /*
        * UpdateCallback is the main interface that is used to compare the elements.
        *   - sortBy() is used to locate new elements passed to SortedList
        *   - updateBy() is used to update/remove elements
        *
        * Typical example would be Message model class which we want to:
        *   - Sort messages according to their dates
        *   - Update/Remove messages according to their randomIDs or IDs.
        * */
        interface UpdateCallback {
            fun sortBy(i1: T, i2: T): Int
            fun updateBy(oldItem: T, newItem: T): Int
        }
    }
    

    The usage is explained here: https://medium.com/@abduazizkayumov/sortedlist-with-recyclerview-part-2-64c3e9b1b124

提交回复
热议问题