MVVM und Auswählen von Elementen in einem Adapter - Basisadapter

So kam ich schließlich zum Höhepunkt meiner Idee mit einer Bibliothek, die die Logik zum Auswählen von Elementen aus einer Liste in einem Adapter enthält. Nach einer plattformunabhängigen Lösung und einer auf LiveData basierenden Bibliothek habe ich etwas geschrieben, mit dem Sie all dies schnell und einfach mit einem Adapter verknüpfen können, um den Gesamtcode zu reduzieren.



SelectListAdapter-Schnittstelle



Beginnen wir mit einer einfachen SelectingListAdapter-Schnittstelle, die ich für einen Adapter mit einer regulären linearen Liste hinzugefügt habe. Nach meiner Erfahrung werden zwischen 90 und 95% der Adapter in dieser Form verkauft.



interface SelectingListAdapter<T> {
    fun setListItems(items: ArrayList<T>)
}


Nichts kompliziertes - nur die Liste der Elemente aktualisieren. Und meiner Meinung nach wird es nicht schwierig sein, diese Schnittstelle zur Liste der in Ihrem Adapter implementierten hinzuzufügen. Wozu? Um beide Erweiterungsmethoden verwenden zu können, die ich als nächstes erwähnen werde:



fun <T> SelectingListAdapter<T>.observeItemsChange(lifecycleOwner: LifecycleOwner,
                                                   liveDataSource: LiveDataSource<T>) {
    liveDataSource.allItems.observe(lifecycleOwner, { items -> setListItems(items) })
}


Die Methode observeItemsChangeabonniert Änderungen an der Liste der Elemente in LiveDataSource.



fun RecyclerView.Adapter<*>.observeSelectionChange(lifecycleOwner: LifecycleOwner,
                                                   liveDataSource: LiveDataSource<*>) {
    liveDataSource.observeSelectionChange(lifecycleOwner) { position, _ ->
        notifyItemChanged(position)
    }
}


Die Methode observeSelectionChangeabonniert bereits Änderungen bei der Auswahl der Elemente. Es gibt nur eine Benachrichtigung, dass das Element aktualisiert werden muss. Im Folgenden wird beschrieben, ob dieses Element bereits ausgewählt ist.



fun <T, TAdapter> TAdapter.observeAllChanges(lifecycleOwner: LifecycleOwner,
                                             liveDataSource: LiveDataSource<T>)
        where TAdapter : RecyclerView.Adapter<*>,
              TAdapter : SelectingListAdapter<T> {
    observeSelectionChange(lifecycleOwner, liveDataSource)
    observeItemsChange(lifecycleOwner, liveDataSource)
}


Wenn Sie beide Methoden gleichzeitig aufrufen möchten, gibt es observeAllChangeseine, die dies in einer Zeile erledigt.



BaseSelectingListAdapter-Klasse



, LiveDataSource, . , :



abstract class BaseSelectingListAdapter<T, VH: BaseSelectingListHolder<T>> 
        : RecyclerView.Adapter<VH>(), SelectingListAdapter<T> {
    var callback: SelectingListAdapterCallback? = null
    ...
}
abstract class BaseSelectingListHolder<T>(itemView: View) : RecyclerView.ViewHolder(itemView) {
    abstract fun bindItem(item: T, isSelected: Boolean, onClick: (() -> Unit)?)
}


, SelectingListAdapterCallback.



interface SelectingListAdapterCallback {
    fun isItemSelected(position: Int): Boolean
    fun clickItem(position: Int)
}


, , , .

BaseSelectingListAdapter , LiveDataSource.



fun <T> setCallback(liveDataSource: LiveDataSource<T>) {
    callback = object : SelectingListAdapterCallback {
        override fun isItemSelected(position: Int) =
            liveDataSource.isItemSelected(position)
        override fun clickItem(position: Int) {
            liveDataSource.clickPosition(position)
        }
    }
}


BaseSelectingListAdapter — , .



    fun fullyInitialize(lifecycleOwner: LifecycleOwner,
                        liveDataSource: LiveDataSource<T>) {
        observeAllChanges(lifecycleOwner, liveDataSource)
        setCallback(liveDataSource)
    }


fullyInitialize, . . , , .



onCreateViewHolder bindItem. -, boilerplate .



class MyAdapter : BaseSelectingListAdapter<User, MyHolder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
        MyHolder(...)//create your holder view
}
class MyHolder(itemView: View) : BaseSelectingListHolder<User>(itemView) {
    override fun bindItem(item: User, isSelected: Boolean, onClick: (() -> Unit)?) {
        //bind your data
    }
}




, . - , , :



  1. .
  2. ( , ), SelectionManager'.




:





Links in Gradle:



implementation 'ru.ircover.selectionmanager:core:1.1.0'

implementation 'ru.ircover.selectionmanager:livesource:1.0.1'

implementation 'ru.ircover.selectionmanager:selectingadapter:1.0.0'




All Articles