0

I want to fetch all the Video files from the Firebase Storage and display them in the RecyclerView. I have managed to get all the files, but I am not able to update the RecyclerView once I get all the files retrieved. Here is the code

 recyclerViewVideoList.setHasFixedSize(true)
 recyclerViewVideoList.layoutManager = LinearLayoutManager(this)
 recyclerViewVideoList.adapter = VideoListRecyclerViewAdapter(applicationContext,videoList, this)
 getVideos()

 private fun getVideos() {
    val listRef = firebaseStorage.reference.child("videos")
    listRef.listAll()
        .addOnSuccessListener { listResult ->
            listResult.items.forEach { item ->
                item.downloadUrl.addOnSuccessListener {
                    videoList.add(Video(item.name, it.toString(), "565656"))
                }
            }
           recyclerViewVideoList.adapter!!.notifyDataSetChanged()
        }
        .addOnFailureListener {
            Toast.makeText(applicationContext, "Something went wrong. Please try again", Toast.LENGTH_SHORT).show()
        }
}

There is a solution here, but it calls the notifyDataSetChanged() multiple times. I want to avoid doing that.

2 Answers2

1

A more effective solution is to call the notifyDataSetChanged() function only for the last element of the list item. By doing this your notifyDataSetChanged() function executed for only last element and update all the recycler view.

Change this:

   .addOnSuccessListener { listResult ->
        listResult.items.forEach { item ->
            item.downloadUrl.addOnSuccessListener {
                videoList.add(Video(item.name, it.toString(), "565656"))
            }
        }
       recyclerViewVideoList.adapter!!.notifyDataSetChanged()
    }

this

//Declare one integer count variable var count = 0

     .addOnSuccessListener { listResult ->
        listResult.items.forEach { item ->
            item.downloadUrl.addOnSuccessListener {
                videoList.add(Video(item.name, it.toString(), "565656"))
                count++
                if(count == listResult.items.size)
                   recyclerViewVideoList.adapter!!.notifyDataSetChanged()  
            }
        }
    }
Rohit Suthar
  • 967
  • 9
  • 22
0

Change this:

         .addOnSuccessListener { listResult ->
            listResult.items.forEach { item ->
                item.downloadUrl.addOnSuccessListener {
                    videoList.add(Video(item.name, it.toString(), "565656"))
                }
            }
           recyclerViewVideoList.adapter!!.notifyDataSetChanged()
        }

into this:

        .addOnSuccessListener { listResult ->
            listResult.items.forEach { item ->
                item.downloadUrl.addOnSuccessListener {
                    videoList.add(Video(item.name, it.toString(), "565656"))
                    recyclerViewVideoList.adapter!!.notifyDataSetChanged()
                }
            }
Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
  • This will work, but the adapter will get updated for each iteration of for each loop. I want the code to get all the files and then update the adapter. – Harikrishnan VK Mar 30 '20 at 12:43
  • The code that you are using is asynchronous, the reason why it doesn't work in your code is because the `notifyDataSetChanged()` is getting called before even retrieving the data, that's why you put it under `add()` – Peter Haddad Mar 30 '20 at 12:45
  • I get that. But can I some how manage to update the list without calling the notifyDataSetChanged() multiuple times ? – Harikrishnan VK Mar 30 '20 at 12:49
  • no this is the only way if you are following the mvvm pattern, you can use livedata and set the value then in the fragment/activity when you observe you can call notifyDataSetChanged() – Peter Haddad Mar 30 '20 at 13:02
  • Do you have any link to some example / documentation that could help me with that ? – Harikrishnan VK Mar 30 '20 at 13:07
  • https://developer.android.com/topic/libraries/architecture/livedata#observe_livedata_objects but i think its the same as adding it under `add()` in terms of updating for each iteration. Because the `observe()` method will get called whenever there are data changes in the livedata – Peter Haddad Mar 30 '20 at 13:11
  • Yes, you are right. I think the only option I have is to call notifyDataSetChanged again and again – Harikrishnan VK Mar 30 '20 at 13:24