Então, finalmente cheguei ao ponto culminante da minha ideia com uma biblioteca que inclui a lógica para selecionar itens de uma lista em um adaptador. Depois de uma solução independente de plataforma e uma biblioteca baseada em LiveData , escrevi algo para ajudá-lo a vincular tudo isso de forma rápida e fácil a um adaptador para reduzir o código geral.
Interface SelectingListAdapter
Vamos começar com uma interface SelectingListAdapter simples que adicionei para um adaptador com uma lista linear regular. Na minha experiência, algo em torno de 90-95% dos adaptadores são vendidos nesta forma.
interface SelectingListAdapter<T> {
fun setListItems(items: ArrayList<T>)
}
Nada complicado - apenas atualizando a lista de itens. E, na minha opinião, não será difícil adicionar esta interface à lista das implementadas em seu adaptador. Pelo que? Ser capaz de usar os dois métodos de extensão, que mencionarei a seguir:
fun <T> SelectingListAdapter<T>.observeItemsChange(lifecycleOwner: LifecycleOwner,
liveDataSource: LiveDataSource<T>) {
liveDataSource.allItems.observe(lifecycleOwner, { items -> setListItems(items) })
}
O método se observeItemsChange
inscreve nas alterações da lista de itens em LiveDataSource
.
fun RecyclerView.Adapter<*>.observeSelectionChange(lifecycleOwner: LifecycleOwner,
liveDataSource: LiveDataSource<*>) {
liveDataSource.observeSelectionChange(lifecycleOwner) { position, _ ->
notifyItemChanged(position)
}
}
O método observeSelectionChange
já subscreve mudanças na seleção de itens. Aqui, há apenas uma notificação de que o elemento precisa ser atualizado. Verificar se este item já está selecionado será descrito abaixo.
fun <T, TAdapter> TAdapter.observeAllChanges(lifecycleOwner: LifecycleOwner,
liveDataSource: LiveDataSource<T>)
where TAdapter : RecyclerView.Adapter<*>,
TAdapter : SelectingListAdapter<T> {
observeSelectionChange(lifecycleOwner, liveDataSource)
observeItemsChange(lifecycleOwner, liveDataSource)
}
Bem, se você deseja chamar os dois métodos ao mesmo tempo, existe observeAllChanges
um que o fará em uma linha.
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
}
}
, . - , , :
- .
- ( , ),
SelectionManager
'.
:
- SelectionManager - GitHub
- LiveSource - GitHub
- SelectingAdapter - GitHub
Links no 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'