Я успешно прочитал данные из Firebase и асинхронно отобразил их в imageView, используя обратный вызов завершения. Поскольку я новичок в программировании, мне все еще трудно понять некоторые механизмы, связанные с обратными вызовами, и надеюсь, что кто-то будет любезен пролить свет на некоторые из моих вопросов. Я уже прочитал и просмотрел несколько руководств и объяснений, но все еще не могу понять некоторые концепции. Вот мой код Firebase:
Часть 1:
readFirebaseData(object: FirebaseCallback{
override fun onCallback(list: MutableList<RecipeTemplate>) {
glideVariable?.loadImageUrl(recipeArray[1].recipeImage) //WORKS!!
}
})
Часть 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
Часть 3:
interface FirebaseCallback {
fun onCallback(list: MutableList<RecipeTemplate>)
}
Главное, что я не понимаю сути интерфейса и всей функции-части переопределения (ЧАСТЬ 1). Дело в том, что я успешно проделал то же самое, просто используя вызов функции в конце кода Firebase. Он требует гораздо меньше кода, его легче понять и понять, и, насколько я могу судить, он делает то же самое. Это выглядит так:
Внутри ЧАСТИ 2:
test(recipeArray) //SIMPLY CALLING A FUNCTION INSTEAD OF THE CODE PREVIOUSLY USED.
//firebaseCallback.onCallback(recipeArray)
Затем сама тестовая функция:
fun test(list: MutableList<RecipeTemplate>) {
Log.d("TAGM", "DONE WITH FB")
glideVariable?.loadImageUrl(recipeArray[3].recipeImage)
}
Итак, что мне здесь не хватает? Зачем использовать весь интерфейс обратного вызова?
Чтобы решить эту проблему, вам нужно создать собственный обратный вызов, чтобы дождаться, пока Firebase вернет вам данные. Для этого сначала нужно создать interface следующим образом:
interface FirebaseCallback {
fun onCallback(list: MutableList<RecipeTemplate>)
}
Затем вам нужно создать функцию, которая фактически получает данные из базы данных. Эта функция должна выглядеть так:
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) {}
})
}
В конце просто вызовите функцию readData() и передайте экземпляр интерфейса FirebaseCallback в качестве аргумента везде, где вам это нужно, вот так:
readFirebaseData(object : FirebaseCallback {
override fun onCallback(list: MutableList<RecipeTemplate>) {
//Do what you need to do with your list
}
})
Это единственный способ использовать это значение вне функции onDataChange().