Reputation: 689
I have successfully read data from Firebase
and displayed it in an imageView
asynchronously using a completion callback. Being new to programming, I'm still having a hard time understanding some of the mechanisms around callbacks and hope someone would be kind to shed some light to some of my questions. I have already read and watched multiple tutorials and explanations, but still struggle understanding some concepts. Here is my Firebase
code:
Part 1:
readFirebaseData(object: FirebaseCallback{
override fun onCallback(list: MutableList<RecipeTemplate>) {
glideVariable?.loadImageUrl(recipeArray[1].recipeImage) //WORKS!!
}
})
Part 2:
fun readFirebaseData(firebaseCallback: FirebaseCallback) {
ref!!.addValueEventListener(object: ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot?) {
for (item in snapshot!!.children) {
var tempRecipe = RecipeTemplate()
val image = item.child("recipeImageFirebase")
tempRecipe.recipeImage = image.value.toString()
recipeArray.add(tempRecipe)
}
//INSERTING CODE HERE AT LATER STAGE... SEE LATER IN POST
firebaseCallback.onCallback(recipeArray)
}//END ON DATA CHANGE METHOD
}) //END FB
}//END READ DATA
Part 3:
interface FirebaseCallback {
fun onCallback(list: MutableList<RecipeTemplate>)
}
The main thing is that I don't understand the point of the interface, and the whole override function-part (PART 1). Thing is, I successfully did the very same thing just using a function call at the end of the Firebase
code. It requires way less code and is easier to follow and understand, and from what I can tell, it does the same thing. It looks like this:
Inside PART 2:
test(recipeArray) //SIMPLY CALLING A FUNCTION INSTEAD OF THE CODE PREVIOUSLY USED.
//firebaseCallback.onCallback(recipeArray)
Then the test function itself:
fun test(list: MutableList<RecipeTemplate>) {
Log.d("TAGM", "DONE WITH FB")
glideVariable?.loadImageUrl(recipeArray[3].recipeImage)
}
So, what am I missing here? Why use the whole interface callback thing?
Upvotes: 0
Views: 1165
Reputation: 138824
To solve this, you need to create your own callback to wait for Firebase to return you the data. To achieve this, first you need to create an interface
like this:
interface FirebaseCallback {
fun onCallback(list: MutableList<RecipeTemplate>)
}
Then you need to create a function that is actually getting the data from the database. This function should look like this:
fun readFirebaseData(firebaseCallback: FirebaseCallback) {
ref.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val list = ArrayList<RecipeTemplate>()
for (ds in dataSnapshot.getChildren()) {
val recipeTemplate = ds.getValue(RecipeTemplate::class.java!!)
list.add(recipeTemplate)
}
firebaseCallback.onCallback(list)
}
override fun onCancelled(databaseError: DatabaseError) {}
})
}
In the end just simply call readData()
function and pass an instance of the FirebaseCallback
interface as an argument wherever you need it like this:
readFirebaseData(object : FirebaseCallback {
override fun onCallback(list: MutableList<RecipeTemplate>) {
//Do what you need to do with your list
}
})
This is the only way in which you can use that value outside onDataChange()
function.
Upvotes: 2