Reputation: 1059
What I'm doing here is getting users groups as hashmap, then getting each group's info and doing other stuff with it. But at the end of the foreach loop my "groups" list is empty. Is there anything I can do to wait for foreach loop to finish? Thank you.
db
.child("users")
.child(firebaseUser.uid)
.get()
.addOnCompleteListener { task ->
if (task.isSuccessful) {
val document = task.result
if (document != null && document.value != null) {
val groupsObject =
document.value["groups"] as HashMap<String, Boolean>
for (groupID in groupsObject.keys) {
db
.child("groups/$groupID")
.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
db
.child("users")
.child(friendID)
.get()
.addOnCompleteListener { task ->
// check for something
// add to groups list if data is OK
}
}
override fun onCancelled(error: DatabaseError) {
// TODO: ...
}
})
}
// here "groups" data is empty, because that for each loop above
// hasn't finshed yet looping, and thus my list is displayed empty
groupsAdapter = GroupsAdapter(this@GroupsActivity, groups)
recyclerView.adapter = groupsAdapter
}
}
}
Upvotes: 1
Views: 288
Reputation: 600131
There is no way to wait for all data to be loaded without blocking the user from using your app. That's why the rule of thumb is always the same: any code that needs the data from the database needs to be inside the addOnCompleteListener
callback, or be called from there.
The idiomatic way is to not wait for the data to be loaded, but instead tell the adapter about the new data as it comes in. You can do that by calling notifyDataSetChanged
inside your addOnCompleteListener
:
db
.child("groups/$groupID")
.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
db
.child("users")
.child(friendID)
.get()
.addOnCompleteListener { task ->
// check for something
// add to groups list if data is OK
groupsAdapter.notifyDataSetChanged()
}
}
In cases where you really must run some code after all data has loaded, a common approach is to keep a counter of the number of friends you've already loaded, and check against that inside the addOnCompleteListener
.
So something like:
.addOnCompleteListener { task ->
// check for something
// add to groups list if data is OK
if (friendsLoadedCount++ === groupsObject.keys.size()) {
// TODO: all friends have loaded, so do something with them
}
}
Upvotes: 1