我找不到使用 MVVM 架构在 ListAdapter 中选择状态的好方法。我还在使用@Doug Stevenson 为 Firestore 实现的存储库 LiveData
我试图避免notifyDataSetChanged()
,因为在 UI 上造成明显的故障
在几天的尝试中,这是我最后一次尝试,因为oldList
它被保存为参考,所以DiffUtil.ItemCallback
没有检测到任何变化。似乎我需要对列表进行深度克隆,但我认为必须有更好的性能解决方案。
主视图模型
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
}
....
}
主要片段
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
}
主适配器
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)
}
}