skip to Main Content

My app is an app that gets data from Firebase, and then shows the data in RecyclerView.
I had a few problems and solved the problems by searching, but I have some questions.

First, here is my code.

val productList = mutableListOf<Product>()
database.get().addOnSuccessListener {
    for (item in it.children) {
        productList.add(Product(item.key.toString(), item.child("name").value.toString(), item.child("photo").value.toString(), item.child("content").value.toString(), decimal.format(item.child("price").value.toString().toInt()).toString() + " P", item.child("price").value.toString().toInt()))
    }
    binding.pointMallHomeRecyclerView.adapter?.notifyDataSetChanged() // THIS POINT IS THAT I'M CURIOUST ABOUT
}

val myDataset = productList
val adapter = PointMallMainItemAdapter(requireContext(), myDataset, object: PointMallMainItemAdapter.OnItemClickListener {
    override fun onItemClick(v: View, position: Int, id: String, content: String, photo: String) {
        val action = PointMallHomeFragmentDirections.actionPointMallHomeFragmentToPointMallItemFragment(productId = id, content = content, photo = photo)
        findNavController().navigate(action)
    }
})
binding.pointMallHomeRecyclerView.adapter = adapter

When I coded it first, there isn’t the

binding.pointMallHomeRecyclerView.adapter?.notifyDataSetChanged()

That way, there are data in the ‘productList’, but nothing appears in the RecyclerView.

But, after I added that code, it works. Why does it happen? Doesn’t the code work sequentially? Is it because connecting the adapter runs faster than getting data from the DB? If it works sequentially, if the app gets all the data, it connects the adapter, right?

2

Answers


  1. There is nothing displayed in your RecyclerView because your productList is empty when you’re using:

    val myDataset = productList
    

    Why? Because the Firebase API is asynchronous. And it’s normal behavior since reading a list of objects takes time. The solution is simple and always the same, any code that needs data from a Firebase database needs to be inside the onSuccess() method, or be called from there. In your particular case, you have to move the above line of code right inside the callback:

    val productList = mutableListOf<Product>()
    database.get().addOnSuccessListener {
        for (item in it.children) {
            productList.add(Product(item.key.toString(), item.child("name").value.toString(), item.child("photo").value.toString(), item.child("content").value.toString(), decimal.format(item.child("price").value.toString().toInt()).toString() + " P", item.child("price").value.toString().toInt()))
        }
        val myDataset = productList //👈
        binding.pointMallHomeRecyclerView.adapter?.notifyDataSetChanged()
    }
    

    You might also be interested in reading my answer in the following post regarding the Realtime Database:

    And another one regarding Firestore:

    Login or Signup to reply.
  2. notifyDataSetChanged()
    

    is, as the name mentions, responsible for notifying the adapter that new data has been introduced into the adapter.
    Without this call the adapter will not be updated automatically.

    Note, however, that this call recalculates ALL items in the adapter. This costs computing time.
    If you are simply updating one or just a view parts of the list, use the notifyItemRangeChanged(int start, int end) or notifyItemChanged(int position) instead of notifiyDataSetChanged().

    More info can be found here: https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#notifyItemRangeChanged(int,%20int)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search