Home > OS >  How to await for firestore database to fetch data before returning it
How to await for firestore database to fetch data before returning it

Time:01-20

I am using the Firestore database and need to fetch some data from it. How do I make the function await for the data before returning the list?

fun getExercise(bodyPart: String): MutableList<String> {
        val db = Firebase.firestore
        val exercisesList = mutableListOf<String>()

        val exercise = db.collection("exercises")
        val query = exercise.whereEqualTo("body-part", bodyPart)
        query.get().addOnSuccessListener { result ->
            for(temp in result) {
                exercisesList.add(temp.id)
                Log.d(TAG, "${temp.id} => ${temp.data}")
            }
        }
            .addOnFailureListener { exception ->
                Log.w(TAG, "Error getting documents: ", exception)
            }

        return exercisesList

}

I know I need to use .await() but I am new to Kotlin and can't make it work.

CodePudding user response:

I see 2 possible options:

1. Change your code in order to call another function with the result instead of returning the result

fun getExercise(bodyPart: String) {
        val db = Firebase.firestore
        val exercisesList = mutableListOf<String>()

        val exercise = db.collection("exercises")
        val query = exercise.whereEqualTo("body-part", bodyPart)
        query.get().addOnSuccessListener { result ->
            for(temp in result) {
                exercisesList.add(temp.id)
                Log.d(TAG, "${temp.id} => ${temp.data}")
            }
            // Call another function with the result:
            anotherFunction(exercisesList)
        }.addOnFailureListener { exception ->
            Log.w(TAG, "Error getting documents: ", exception)
        }
}

2. Implement Kotlin Coroutines

This option might be a little more complex than the first one for someone who's new to the language, as you'd need to understand the concept of Kotlin Coroutines.

  1. Start by adding the Coroutines dependency to your build.gradle file:
dependencies {
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
}
  1. Change your function to become a suspend function:
suspend fun getExercise(bodyPart: String): MutableList<String> {
// ...
}
  1. Use the await() extension function to fetch the result:
suspend fun getExercise(bodyPart: String): MutableList<String> {
    val db = Firebase.firestore
    val exercisesList = mutableListOf<String>()

    val exercise = db.collection("exercises")
    val query = exercise.whereEqualTo("body-part", bodyPart)

    try {
        val result = query.get().await()
        for (temp in result) {
            exercisesList.add(temp.id)
            Log.d(TAG, "${temp.id} => ${temp.data}")
        }

        return exercisesList
    } catch (e: Exception) {
        Log.w(TAG, "Error getting documents: ", exception)

        return emptyList() // returning an empty list in case the fetch fails
    }
}
  1. Use a Coroutine scope when making a call to your suspend function:
// If you're calling from an Activity/Fragment, you can use the
// lifecycleScope from the lifecycle-runtime-ktx library
//
// If you're calling from a ViewModel, consider using the
// viewModelScope from the lifecycle-viewmodel-ktx library
//
// See https://d.android.com/topic/libraries/architecture/coroutines#dependencies
// for more details
lifecycleScope.launch { // Coroutine Scope
    val exercises: MutableList<String> = getExercise("arms")
    // use the list
}

More resources:

  • Related