1

I'm new to Firestore and Kotlin and I'm trying to make a function that retrieves a few documents and then putting them in a list so I can access them later, but it returns null. I understand that this it's cause Firestore is async so it takes a while for all the queries to finish. I got it to work by adding a delay for 3 seconds but this doesn't sound like a good solution to the problem as some people might have a slow internet etc. I have tried to use coroutines to fix the issue but I don't really understand how they work.

Here's the function, it's inside another class called DatabaseController:

fun documentsBetweenDates(date1 : String, date2 : String) : MutableList<String> {
    val db = FirebaseFirestore.getInstance()
    val retrievedDocuments = mutableListOf<String>()

    db.collection("users").document(getUID())
        .collection("values")
        .whereGreaterThanOrEqualTo("purchaseDate", convertDateToMillis(date1)!!)
        .whereLessThanOrEqualTo("purchaseDate", convertDateToMillis(date2)!!)
        .get()
        .addOnSuccessListener { document ->
            for (documents in document) {
                retrievedDocuments.add(documents.id)
                Log.d("DB", "Document between dates found: ${retrievedDocuments}")
            }
        }

    return retrievedDocuments
}

Here is how I'm calling the method from my fragment:

var test = dbController.documentsBetweenDates("22/02/2021", "22/02/2022")
Log.d("DB", test.ToString())

Adding a delay but it feels like a bad practice, tried using coroutines but I don't understand how they work.

  • There is no way you can do that. Firebase API is asynchronous. So please check the duplicates to see how can you solve this using a callback. You might also be interested in reading this [resource](https://medium.com/firebase-tips-tricks/how-to-read-data-from-cloud-firestore-using-get-bf03b6ee4953). – Alex Mamo Oct 30 '22 at 13:45

1 Answers1

0

So as you pointed out "return retrievedDocuments" does not wait the process to end. You need to do your things inside of "addOnSuccessListener" where the process ended, and do not return like you do.

In your fragment you are calling that db function like so (in OnCreate or whereever you want):

dbController.documentsBetweenDates("22/02/2021", "22/02/2022", this)

Your db function get the call and start work after that:

fun documentsBetweenDates(date1 : String, date2 : String, fragment: YourFragment) {
    val db = FirebaseFirestore.getInstance()
    val retrievedDocuments = mutableListOf<String>()
    db.collection("users").document(getUID())
        .collection("values")
        .whereGreaterThanOrEqualTo("purchaseDate", convertDateToMillis(date1)!!)
        .whereLessThanOrEqualTo("purchaseDate", convertDateToMillis(date2)!!)
        .get()
        .addOnSuccessListener { document ->
            for (documents in document) {
                retrievedDocuments.add(documents.id)
                Log.d("DB", "Document between dates found: ${retrievedDocuments}")
            }
        // Now use retrievedDocuments in here
        // if you want to send this to the fragment where you call this function, 
        // just create another function on there and send this data to there like below.
        fragment.getMyList(retrievedDocuments)
        }
}

And create this function in your fragment to retrieve coming data from documentsBetweenDates function:

   fun getMyList(myList: MutableList<String>) {
     var test = myList
     Log.d("DB", test.ToString())
   }
Mert
  • 904
  • 4
  • 9
  • 21