@ArturPendragonOfficial

Как правильно использовать ViewModel в RecyclerView?

Пожалуйста помогите !
Мне нужно сделать так чтобы мои 5 элементов появлялись в recyclerView и при нажатии кнопки удалить они удалялись.
Так же при повороте экрана все должно сохранятся. Вот и подошли к моей проблеме.
При повороте экрана список загружается заново. Все что я удалил стерлось.(Activity разрушен) :((
Я решил делать через ViewModel. И уже 2-рой день сижу и не могу понять в чем ошибка. Почему мой код не работает...
Очень прошу прям тыкнуть меня носом в проблемное место в коде.

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
    }
}


На данный момент код который я выложил при нажатии на элемент в recyclerView полностью все стирает !
  • Вопрос задан
  • 865 просмотров
Решения вопроса 1
iLLuzor
@iLLuzor
Java, Kotlin, Android Developer
Этот код в данном случае не имеет смысла и его нужно удалить:
notifyItemRangeChanged(positionForDelete,myArrayElement.size)


Что ещё следует изменить:
- Сделать ViewModel полем класса активити;
- Не передавать ViewModel в адаптер. Адаптер вообще не должен знать о модели;
- Передавать список в адаптер не через конструктор, а через отдельный метод.

Как обрабатывать клик:
При клике по холдеру ничего не удалять из списка адаптера, а сообщать в активити через колбэк о том, что был клик по элементу, а из активити сообщать об этом клике во ViewModel через вызов метода. Далее ViewModel должна решать, что делать - в вашем случае удалить элемент и передать новый список в активити, которая передаст его в адаптер.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы