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 observeItemsChange
abonniert Änderungen an der Liste der Elemente in LiveDataSource
.
fun RecyclerView.Adapter<*>.observeSelectionChange(lifecycleOwner: LifecycleOwner,
liveDataSource: LiveDataSource<*>) {
liveDataSource.observeSelectionChange(lifecycleOwner) { position, _ ->
notifyItemChanged(position)
}
}
Die Methode observeSelectionChange
abonniert 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 observeAllChanges
eine, 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
}
}
, . - , , :
- .
- ( , ),
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'