Android - my recyclerview is not showing data

Viewed 1360

I am a junior programmer here trying to create an MVVM application in Android using Kotlin. I am trying to create a housing app that retrieves houses from an API then shows them in a recycler view.

The problem is that my recycler view is empty. I do have an adapter and maybe there is something going wrong. I believe they're not being paired together correctly

Anyway, I'm going to show my fragment class.

class HousesFragment : Fragment() {

private lateinit var factory: HousesViewModelFactory
private lateinit var viewModel: HousesViewModel
private lateinit var rv: RecyclerView
private lateinit var adapter: HousesAdapter


override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    return inflater.inflate(R.layout.houses_fragment, container, false)
}


override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    val api = HouseApi()
    val repo = HouseRepo(api)
    factory = HousesViewModelFactory(repo)
    viewModel = ViewModelProviders.of(this, factory).get(HousesViewModel::class.java)
    rv = view?.findViewById(R.id.rvHouses) ?: return

    //use the adapter
    viewModel.getHouses()
    viewModel.houses.observe(viewLifecycleOwner, Observer { houses ->
        rv.also {

            it.layoutManager = LinearLayoutManager(requireContext())
            it.adapter = HousesAdapter(houses, this)
            it.setHasFixedSize(true)

            rv.adapter = it.adapter


        }
    })


}

}

I think that this code in particular is causing the problem

rv.also {

            it.layoutManager = LinearLayoutManager(requireContext())
            it.adapter = HousesAdapter(houses, this)
            it.setHasFixedSize(true)

            rv.adapter = it.adapter


        }

the reason why I say that is because this code is responsible for matching the recyclerview with the adapter.

I'll explain other things I tried. I tried to implement other people's code and see how their's works. I did so by going on Youtube and checking a bunch of tutorials. Nothing has worked so far, and it's not ideal to do this. I'm trying my best to get past this error. Looking at examples is the best I could do. I'm a junior programmer and don't yet possess the skill of debugging everything on my own

Thank you

EDIT:

here's the adapter:

class HousesAdapter(
    private val houses: List<HouseItem>,
    housesFragment: HousesFragment
) : RecyclerView.Adapter<HousesAdapter.HousesViewHolder>() {

    override fun getItemCount() = houses.size

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
        HousesViewHolder(
            DataBindingUtil.inflate(
                LayoutInflater.from(parent.context),
                R.layout.recyclerview_house,
                parent,
                false
            )
        )

    override fun onBindViewHolder(holder: HousesViewHolder, position: Int) {
        holder.recyclerviewHouseBinding.house = houses[position]
    }

    inner class HousesViewHolder(

        val recyclerviewHouseBinding: RecyclerviewHouseBinding

    ) : RecyclerView.ViewHolder(recyclerviewHouseBinding.root)
}

enter image description here

enter image description here

The fix:

Turns out I didn't put textviews inside the cardview. I totally forgot about that step and it was my mistake. Hopefully this post can serve as a reminder to others to populate their cardviews too and make sure it's filled. This'll also serve as a reminder for me. Very stupid mistake indeed, but now I'm sure I won't repeat it.

A big thanks to everyone who commented

1 Answers

There are a few fixes to make:

  1. You call getHouses first and then observe the data. Where as you should observe the data and then call getHouses.
  2. Only set the RecyclerViews layoutManager and setHasFixedSize once.
  3. Remove rv.adapter = it.adapter that seems redundant due to this line: it.adapter = HousesAdapter(houses, this).
  4. This line seems a bit much rv = view?.findViewById(R.id.rvHouses) ?: return so if view or RecyclerView is null we return, something tells me this should never be the case.

Here would be an example with all my recommended changes made:

    rv = view!!.findViewById(R.id.rvHouses)
    rv.layoutManager = LinearLayoutManager(requireContext())
    rv.setHasFixedSize(true)
    viewModel.houses.observe(viewLifecycleOwner, Observer { houses ->
        rv.adapter = HousesAdapter(houses, this)
    })
    viewModel.getHouses()
  1. Your onBindViewHolder method seems suspect, looking at examples you should have something similar to:

     override fun onBindViewHolder(holder: BindingHolder, position: Int) {
         item: T = items.get(position)       
         holder.binding.setVariable(BR.item, item);            
         holder.binding.executePendingBindings();
     }
    
Related