Я не могу найти хороший способ для выбранного состояния в ListAdapter с использованием архитектуры MVVM. Я также использую репозиторий LiveData, реализованный для firestore @Doug Stevenson
Я пытаюсь избежать notifyDataSetChanged()
, так как это вызывает заметный сбой в пользовательском интерфейсе
В течение нескольких дней попыток это мой последний попытка, которая не работает, поскольку oldList
сохраняется как ссылка, поэтому DiffUtil.ItemCallback
не обнаруживает никаких изменений. Похоже, мне нужно выполнить глубокое клонирование в список, но я считаю, что должно быть решение с более высокой производительностью.
MainViewModel
class MainViewModel @ViewModelInject constructor(private val glistRepo: GlistRepository): ViewModel() {
private val selected = MutableLiveData<HashMap<String,Glist>>()
init {
selected.value = HashMap()
}
fun getSelected(): LiveData<HashMap<String,Glist>> {
return selected
}
fun onItemClicked(glist: Glist) {
selected.value?.set(glist.id, glist)
selected.value = selected.value //inform observers
}
....
}
MainFragment
viewModel.getSelected().observe(viewLifecycleOwner, Observer {
adapter.setSelected(it.keys.toList())
})
RepositoryCommon
Для выбранного состояния я добавил объект sel
, но, поскольку я не хочу добавлять его в базу данных, я добавил в интерфейс оболочки
interface QueryItem<T> {
val item: T
val id: String
var sel: Boolean //The selected state
}
MainAdapter
class MainAdapter(private val clickListener: MainAdapterListener):
ListAdapter<QueryItem<Glist>, MainAdapter.ViewHolder>(asyncDifferConfig) {
private val selected = HashSet<String>()
private var oldList: List<QueryItem<Glist>>? = ArrayList()
fun setSelected(list: List<String>) {
selected.clear()
selected.addAll(list)
//Instead of using notifyDataSetChanged() i am trying to trigger the diffUtil. Not working!
submitList(oldList)
}
override fun submitList(list: List<QueryItem<Glist>>?) {
if (selected.size != 0 && oldList != null && oldList!!.isNotEmpty()) {
var id: String
for (i in oldList!!.indices) {
oldList!![i].sel = false
id = oldList!![i].id
selected.forEach { key ->
if (id == key) {
oldList!![i].sel = true
}
}
}
}
oldList = list
super.submitList(oldList)
}
QueryItemDiffCallback
open class QueryItemDiffCallback<T> : DiffUtil.ItemCallback<QueryItem<T>>() {
override fun areItemsTheSame(oldItem: QueryItem<T>, newItem: QueryItem<T>): Boolean {
return (oldItem.id == newItem.id && oldItem.sel == newItem.sel)
}
@SuppressLint("DiffUtilEquals") // equals() is OK for data classes
override fun areContentsTheSame(oldItem: QueryItem<T>, newItem: QueryItem<T>): Boolean {
return (oldItem.item == newItem.item && oldItem.sel == newItem.sel)
}
}