MVVM et sélection d'éléments dans l'adaptateur - Adaptateur de base

Donc, je suis finalement arrivé au point culminant de mon idée avec une bibliothèque qui inclut la logique de sélection des éléments d'une liste dans un adaptateur. Après une solution indépendante de la plateforme et une bibliothèque basée sur LiveData , j'ai écrit quelque chose pour vous aider à relier rapidement et facilement tout cela à un adaptateur pour réduire le code global.



Interface SelectingListAdapter



Commençons par une simple interface SelectingListAdapter que j'ai ajoutée pour un adaptateur avec une liste linéaire régulière. D'après mon expérience, entre 90 et 95% des adaptateurs sont vendus sous cette forme.



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


Rien de compliqué - il suffit de mettre à jour la liste des éléments. Et, à mon avis, il ne sera pas difficile d'ajouter cette interface à la liste de celles implémentées dans votre adaptateur. Pourquoi? Pour pouvoir utiliser les deux méthodes d'extension, que je mentionnerai ensuite:



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


La méthode observeItemsChanges'abonne aux modifications apportées à la liste des éléments dans LiveDataSource.



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


La méthode observeSelectionChangesouscrit déjà aux changements dans la sélection des articles. Ici, il n'y a qu'une notification indiquant que l'élément doit être mis à jour. Vérifier si cet élément est déjà sélectionné sera décrit ci-dessous.



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


Eh bien, si vous voulez appeler les deux méthodes à la fois, il y en a observeAllChangesune qui le fera sur une seule ligne.



Classe BaseSelectingListAdapter



, 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'.




:





Liens dans 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