I am beginner to android development. I am trying to implement recycler view that shows a list of groups after downloading it from firebase database. The function loadGroups() is called from main activity to return a list which is then fed to recycler view adapter. The data is being downloaded correctly but seems like myList is returned first and elements from firebase are added a few millis later. I want the program to wait for the elements to be added to myList and then return it
class DataSource {
private lateinit var myDatabase: DatabaseReference
var myList : MutableList<Group> = mutableListOf<Group>();
fun loadGroups(): MutableList<Group> {
// Here I want to let the loadGroupsFromFirebase() complete adding groups to mylist
// after that is completed, mylist should be returned
loadGroupsFromFirebase()
Log.d("mylist", "returning my list")
return myList
}
private fun loadGroupsFromFirebase(){
myDatabase = FirebaseDatabase.getInstance().getReference("myGroupsList")
val postListener = object : ValueEventListener {
override fun onDataChange(myDataSnapshot: DataSnapshot) {
if(myDataSnapshot.exists()){
Log.d("mylist", "does exist ${myDataSnapshot.getValue().toString()}")
myList.clear()
for(dataSnapshot in myDataSnapshot.children){
val myGroupDetails = dataSnapshot.getValue<Group>()!!;
myList.add(myGroupDetails)
myList.add(Group(myIconId=2131165282, myTitle="G1", myLink = "https://s*****************************************9", numberOfPeople=100))
Log.d("mylist", "does exist CODE 00 ${myList.toString()}")
}
}
else {
Log.d("mylist", "does not exist")
}
}
override fun onCancelled(databaseError: DatabaseError) {
// Getting Post failed, log a message
Log.w("mylist", "loadPost:onCancelled", databaseError.toException())
}
}
myDatabase.addValueEventListener(postListener)
}
}
Any help would be appreciated :) Below is the screenshot of logcat.
CodePudding user response:
ValueEventListener is an interface, so that everything that runs on onDataChange is an asyncronous operation (because depends on network response), in other hand loadGroups() is a synchronous operation, so loadGroupsFromFirebase() is call at first and inmediatly return myList is called, but loadGroupsFromFirebase() is not finish yet.
So you need to use the groups after the for loop
for(dataSnapshot in myDataSnapshot.children){
val myGroupDetails = dataSnapshot.getValue<Group>()!!;
myList.add(myGroupDetails)
myList.add(Group(myIconId=2131165282, myTitle="G1", myLink = "https://s*****************************************9", numberOfPeople=100))
Log.d("mylist", "does exist CODE 00 ${myList.toString()}")
}
//-- HERE, TAKE myList and save it somehow.
Or well, implements MVP or MVVM patters, so you can handle the asyncronous response properly.
CodePudding user response:
Modify your function loadGroupsFromFirebase()
have a unit return
private fun loadGroupsFromFirebase(result: (List<Group>) -> Unit){
myDatabase = FirebaseDatabase.getInstance().getReference("myGroupsList")
val postListener = object : ValueEventListener {
override fun onDataChange(myDataSnapshot: DataSnapshot) {
if(myDataSnapshot.exists()){
Log.d("mylist", "does exist ${myDataSnapshot.getValue().toString()}")
myList.clear()
for(dataSnapshot in myDataSnapshot.children){
val myGroupDetails = dataSnapshot.getValue<Group>()!!;
myList.add(myGroupDetails)
myList.add(Group(myIconId=2131165282, myTitle="G1", myLink = "https://s*****************************************9", numberOfPeople=100))
Log.d("mylist", "does exist CODE 00 ${myList.toString()}")
}
}
else {
Log.d("mylist", "does not exist")
}
result(myList)
}
override fun onCancelled(databaseError: DatabaseError) {
// Getting Post failed, log a message
Log.w("mylist", "loadPost:onCancelled", databaseError.toException())
}
}
myDatabase.addValueEventListener(postListener)
}