如何在RecyclerView上使用LiveData ?



**问题是:我按下按钮删除列表中的一个项目,它被删除了。但是当我旋转屏幕时,列表被重新加载。列表不保存数据。

LiveData未看到更改。如何通过它传递一个带有删除元素的新列表?我花了10个小时解决这个问题(**

<<p> 适配器/strong>
class ItemAdapter(var context: Context, private var arrayList: MutableList<NumberModel>):RecyclerView.Adapter<ItemAdapter.ItemHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemHolder{
    val itemHolder = LayoutInflater.from(parent.context).inflate(
        R.layout.grid_layout_list_item,
        parent,
        false
    )
    return ItemHolder(itemHolder)
}
override fun onBindViewHolder(holder: ItemHolder, position: Int) {
    var positionOfNumber:NumberModel = arrayList.get(position)
    holder.textOfNumber.text = positionOfNumber.numberOfElement
   holder.button.setOnClickListener {
       var positionForDelete = holder.adapterPosition
       arrayList.removeAt(positionForDelete)
       notifyItemRemoved(positionForDelete)
       notifyItemRangeChanged(positionForDelete,arrayList.size)
   }
}
override fun getItemCount(): Int {
    return arrayList.size
}
class ItemHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    var textOfNumber = itemView.findViewById<TextView>(R.id.numberTextView)
    var button:Button = itemView.findViewById(R.id.buttonClick)
}

}

MainActivity

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val list = mutableListOf<NumberModel>()
    adapter = ItemAdapter(this,list)
    recyclerView = findViewById(R.id.recyclerViewList)
    gridLayoutManager = GridLayoutManager(applicationContext,2,LinearLayoutManager.VERTICAL,false)
    recyclerView?.layoutManager = gridLayoutManager
    recyclerView?.setHasFixedSize(true)
    recyclerView?.adapter = adapter
    val model= ViewModelProvider(this).get(MainActivityViewModel::class.java)
    model.getListElements().observe(this, Observer {elementsSnapshot ->
        // Received elements from ViewModel
        list.clear()
        // Take new data from snapshot
        list.addAll(elementsSnapshot)
        adapter?.notifyDataSetChanged()
    })
}

ViewModel

class MainActivityViewModel : ViewModel() {
private val elementsList: MutableLiveData<MutableList<NumberModel>>
init {
    elementsList = MutableLiveData()
    elementsList.value = setElements()
}
fun getListElements() : LiveData<MutableList<NumberModel>>{
   return elementsList
}
private fun setElements() : MutableList<NumberModel> {
    val itemArrayList:MutableList<NumberModel> = ArrayList()
    itemArrayList.add(NumberModel("1"))
    itemArrayList.add(NumberModel("2"))
    itemArrayList.add(NumberModel("3"))
    itemArrayList.add(NumberModel("4"))
    itemArrayList.add(NumberModel("5"))
    return itemArrayList
}

}

改变从ViewModel返回的对象很少是一个好主意。对事件的反应(比如用户点击你的删除按钮)应该在ViewModel中完成。这与响应式UI风格(数据向下,事件向上)是一致的,并且将允许您将逻辑(ViewModel)与UI细节(Activity, Adapter)分离。

你的ViewModel可以暴露两个元素:

class MyViewModel {
    private val localElements = MutableLiveData<List<...>>()
    val elements: LiveData<List<...>> 
        get() = localElements
    fun onElementClicked(index: Int) { 
        // get current value of localElements, make a copy of it with removed value at [index] and publish it to localElements
    }
}

然后,您可以在适配器中公开setElements方法,并在viewModel.elements更改时调用它。你可以把ViewModel的实例传递给你的适配器,当你检测到点击时调用onElementClicked

这样,你可以认为你的Activity和Adapter基本上是"无状态的"。当配置更改时,有效状态将保留在ViewModel中。

p。Android文档建议在构建Activity/Fragment期间检索ViewModel实例:https://developer.android.com/jetpack/guide?authuser=1#build-ui

最新更新