1

I'm writing a function that does a query on firestore documents, and returns them in a list. If there are no documents, return null (or an empty list). I'm not very familiar with Kotlin, I only know Flutter

Kotlin code (what I tried) but it's saying I cannot return inside the listener:

fun getPlaces(type: String): List<DocumentSnapshot>? {
        db.collection("users")
            .whereEqualTo("type", type)
            .get()
            .addOnSuccessListener { documents ->
                if (documents.isEmpty) {
                    return null
                } else {
                    return documents
                }
            }
            .addOnFailureListener { exception ->
                Log.w(TAG, "Error getting documents: ", exception)
            }
    }

Here's the Flutter equivalent of what I'm trying to do:

List<DocumentSnapshot> getDocs(String type) async {
    QuerySnapshot snaps = await db.collection('users').where('type', isEqualTo: type).getDocuments();

    if (snaps.documents.isEmpty) {
        return null;
    } else {
        return snaps.documents;
    }
}

Syntax might be a little off but something like that

3
  • 1
    If you want to do this the "right way" in Kotlin, in the way that most closely matches the dart you've shown, you're going to have to learn Kotlin coroutines with "suspend" functions in order to handle the asynchronous response from the query. If you're new to Kotlin, this is going to require going down the raibbit hole of learning the details of the language and the Android platform frameworks added to it. Commented Nov 30, 2019 at 17:49
  • Also see stackoverflow.com/questions/54738138/… Commented Nov 30, 2019 at 18:15
  • So defining var docs: List<DocumentSnapshot>? = null outside the listener and putting docs = documents.documents inside the listener would not work? I just need to store the documents in a list after doing the query Commented Nov 30, 2019 at 18:51

1 Answer 1

8

This answer is going to assume that you already understand how Kotlin coroutines work in an Android environment. That practice is strongly suggested by the Android platform team.

As you have seen, get() returns immediately with a Task object where you can attach listeners to get the result of the query. What you need to do is convert this into something that works with Kotlin coroutines. There is a library called kotlinx-coroutines-play-services. That will give you an extension function called await() that will suspend the coroutine until the result is available, then return it.

So, add the library to your project like this:

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

Then create a suspend function like this:

private suspend fun getPlaces(type: String): List<DocumentSnapshot> {
    val querySnapshot = db.collection("users")
        .whereEqualTo("type", type)
        .get()
        .await()
    return querySnapshot.documents
}

Then you would call it from another suspend function like this:

private suspend fun foo() {
    try {
        val places = getPlaces("...")
    }
    catch (exception: Exception) {
        Log.w(TAG, "Error getting documents: ", exception)
    }
}

It's up to you to learn how to create a coroutine context in an Android environment so you can start working with suspend functions. A full discussion about that is out of scope for this question. There is a lot of Android doucumentation and tutorials to help with that.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the response, I ended up using something similar to what I had originally (I just needed to create a drop down (spinner) based from documents returned from firestore. It's for a quick school project). But I'll definitely learn your method in the future for more serious apps

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.