Home > Mobile >  How I can do a RecyclerView with MVVM
How I can do a RecyclerView with MVVM

Time:05-12

I am trying to do a recyclerView with mvvm, but I get empty recyclerView as a result any help please! the kt file :

typeRecy = itemView.findViewById(R.id.typeRecy)
        typeRecy.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
        typeRecy.setHasFixedSize(true)
        typeVM = ViewModelProvider(this)[TypeViewModel::class.java]
        typeVM.typeCard.observe(viewLifecycleOwner, Observer {
            typeVM.setList()
            typeRecy.adapter = recyclerAdapter(it)
        })

the viewMoedel :

class TypeViewModel: ViewModel() {

    //
    private lateinit var typeList: ArrayList<TypeCard>
    lateinit var bgType: Array<Int>
    lateinit var nameType: Array<String>
    var typeCard = MutableLiveData<ArrayList<TypeCard>>()
    fun setList(){
        bgType= arrayOf(R.drawable.group_1,R.drawable.group_3,R.drawable.group_4,R.drawable.group_2,R.drawable.group_5,R.drawable.group_8)
        nameType= arrayOf("Pizza", "Tacos", "Salads","Burgers","Soups" , "Drinks")
        typeList = arrayListOf()
        putTypeData()
        //
    }
    fun putTypeData() {
        for(i in nameType.indices){
            val type = TypeCard(nameType[i], bgType[i])
            typeList.add(type)
        }
        typeCard.value = typeList
    }

}

CodePudding user response:

Firstly, do not recreate your adapter each time you get new data. Just instanciate it on the onCreate with an emptyList.

typeRecy = itemView.findViewById(R.id.typeRecy)
        typeRecy.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
        typeRecy.setHasFixedSize(true)
        val recyclerAdapter = recyclerAdapter(emptyList())
        typeRecy.adapter = recyclerAdapter
        typeVM = ViewModelProvider(this)[TypeViewModel::class.java]

Secondly, you don't need two variable (typeCard and typeList) but only one of them that will be the MutableLiveData :

class TypeViewModel : ViewModel() {

    val typeCard = MutableLiveData<ArrayList<TypeCard>>()
    fun setList() {
        arrayOf(
            "Pizza" to R.drawable. group_1,
            "Tacos" to R.drawable. group_3,
            "Salads" to R.drawable. group_4,
            "Burgers" to R.drawable. group_2,
            "Soups" to R.drawable. group_5,
            "Drinks" to R.drawable. group_8
        ).map { (nameType, backgroundType) ->
            TypeCard(nameType, backgroundType)
        }.let(typeCard::postValue)
    }

}

Finally, in the fragment you just need to observe the typeCardLiveData and in your adapter, have a method to update the list and DO NOT call setList each time.


typeRecy = itemView.findViewById(R.id.typeRecy)
        typeRecy.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
        typeRecy.setHasFixedSize(true)
        val recyclerAdapter = recyclerAdapter(emptyList())
        typeRecy.adapter = recyclerAdapter
        typeVM = ViewModelProvider(this)[TypeViewModel::class.java]
        typeVM.setList()
        typeVM.typeCard.observe(viewLifecycleOwner, Observer {
            recyclerAdapter.updateList(it)
        })

CodePudding user response:

From your provided code it looks like typeVM.setList() in your observe callback is never called, since there is no data in the LiveData typeCard to be observed in the first place.

Try moving typeVM.setList() out of the Observer.

Also it would be good to set the adapter to the RecylerView outside of the Observer and only update the data of the adapter, when observing the data of typeCard

CodePudding user response:

the solution was just to move this out of the callback

typeVM.setList()
  • Related