A
A
ArturPendragonOfficial2021-01-16 02:19:14
Android
ArturPendragonOfficial, 2021-01-16 02:19:14

How to properly use ViewModel in RecyclerView?

Please, help !
I need to make my 5 items appear in the recyclerView and when the delete button is clicked, they are deleted.
Also, when you rotate the screen, everything should be saved. Here we come to my problem.
When you rotate the screen, the list is reloaded. Everything that I deleted was erased. (Activity is destroyed) :((
I decided to do it through the ViewModel. And for the 2nd day I’ve been sitting and I can’t understand what the error is. Why my code doesn’t work ...
I beg you to directly poke my nose into the problem place in

code.Adapter

class ItemAdapter(
    var context: Context, var myArrayElement:MutableList<NumberModel>,
    var exemplarLD: MainActivityViewModel
):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 = myArrayElement.get(position)
        holder.textOfNumber.text = positionOfNumber.numberOfElement
       holder.button.setOnClickListener {
           var positionForDelete = holder.adapterPosition
               
           myArrayElement.removeAt(positionForDelete)
           exemplarLD.onElementClicked(myArrayElement)
           notifyItemRemoved(positionForDelete)
           notifyItemRangeChanged(positionForDelete,myArrayElement.size)
       }
    }
    override fun getItemCount(): Int {
        return myArrayElement.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 model= ViewModelProvider(this).get(MainActivityViewModel::class.java)

        var myArrayList:MutableList<NumberModel> = model.setElements()
        recyclerView = findViewById(R.id.recyclerViewList)
        gridLayoutManager = GridLayoutManager(applicationContext,2,LinearLayoutManager.VERTICAL,false)
        recyclerView?.layoutManager = gridLayoutManager
        
        adapter = ItemAdapter(this,myArrayList,model)
        recyclerView?.setHasFixedSize(true)
        
        model.localElements.observe(this,{
            myArrayList.clear()
            myArrayList.addAll(it)
            adapter?.notifyDataSetChanged()
        })
        recyclerView?.adapter = adapter
    }

}


viewmodel

class MainActivityViewModel : ViewModel() {
    
     var localElements = MutableLiveData<List<NumberModel>>()
    
    // Получаем новые данные о массиве.И закидываем в localElements
    fun onElementClicked(newArray: MutableList<NumberModel>) {
        Log.i("LogJo","NewArray is " + newArray.size)
        val copyOfArrayList:MutableList<NumberModel> = newArray
        Log.i("LogJo","size of copyOfArrayList " + copyOfArrayList.size )
        localElements.value = copyOfArrayList
    }
    
    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
    }
}


At the moment, the code that I posted when you click on an element in the recyclerView completely erases everything!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
I
illuzor, 2021-01-16
@ArturPendragonOfficial

This code in this case does not make sense and should be removed:

notifyItemRangeChanged(positionForDelete,myArrayElement.size)

What else should be changed:
- Make ViewModel a field of the activity class;
- Do not pass ViewModel to adapter. The adapter doesn't need to know about the model at all;
- Pass the list to the adapter not through the constructor, but through a separate method.
How to handle a click:
When a holder is clicked, do not delete anything from the adapter list, but inform the activity through the callback that there was a click on the element, and from the activity report this click to the ViewModel through a method call. Next, the ViewModel has to decide what to do - in your case, remove the element and pass the new list to the activity, which will pass it to the adapter.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question