Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return string from Firebase addOnSuccessListener [duplicate]

I'm building an app for a friend and I use Firestore. What I want is to display a list of favorite places but for some reason, the list is always empty.

enter image description here

I cannot get the data from Firestore. This is my code:

fun getListOfPlaces() : List<String> {
    val places = ArrayList<String>()
    placesRef.get().addOnCompleteListener { task ->
        if (task.isSuccessful) {
            for (document in task.result) {
                val name = document.data["name"].toString()
                places.add(name)
            }
        }
    }
    return list;
}

If I try to print, let's say the size of the list in onCreate function, the size is always 0.

Log.d("TAG", getListOfPlaces().size().toString()); // Is 0 !!!

I can confirm Firebase is successfully installed. What am I missing?

like image 581
Jane Ashley Avatar asked May 26 '26 07:05

Jane Ashley


1 Answers

Nowadays, Kotlin provides a simpler way to achieve the same result as in the case of using a callback. This answer is going to explain how to use Kotlin Coroutines. In order to make it work, we need to add the following dependency in our build.gradle file:

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.2.1"

This library that we use is called Module kotlinx-coroutines-play-services and is used for the exact same purpose. As we already know, there is no way we can return a list of objects as a result of a method because get() returns immediately, while the callback from the Task it returns will be called sometime later. That's the reason why we should wait until the data is available.

When calling "get()" on the Task object that is returned, we can attach a listener so we can get the result of our query. What we need to do now is to convert this into something that is working with Kotlin Coroutines. For that, we need to create a suspend function that looks like this:

private suspend fun getListOfPlaces(): List<DocumentSnapshot> {
    val snapshot = placesRef.get().await()
    return snapshot.documents
}

As you can see, we have now an extension function called await() that will interrupt the Coroutine until the data from the database is available and then return it. Now we can simply call it from another suspend method like in the following lines of code:

private suspend fun getDataFromFirestore() {
    try {
        val listOfPlaces = getListOfPlaces()
    } catch (e: Exception) {
        Log.d(TAG, e.getMessage()) //Don't ignore potential errors!
    }
}
like image 196
Alex Mamo Avatar answered May 27 '26 20:05

Alex Mamo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!