0

I've made a function that calls on the FireBase database and will return a MutableList. However, when I try to make it return on a specific line, it says it requires a Unit instead of the MutableList.

fun firebaseCollect(key: String): MutableList<CustomList> {

    var ref = FirebaseDatabase.getInstance().getReference(key)
    var lessonList = mutableListOf<CustomList>()

    ref.addValueEventListener(object: ValueEventListener{
          override fun onCancelled(p0: DatabaseError?) {
          }

          override fun onDataChange(p0: DataSnapshot?) {
              if (p0!!.exists()) {
                  lessonList.clear()
                  for (index in p0.children) {
                      val lesson = index.getValue(CustomList::class.java)
                      lessonList.add(lesson!!)
                  }
                  return lessonList
              }
          }
    })

    return lessonList
}

Type mismatch. Required: Unit, Found: MutableList< CustomList > is found at the first return lessonList since what I am asking for it to return is a MutableList not a Unit. I am confused as to why this happens. The last return would give an empty list. It is currently my first jab at FireBase and this is a practice I am doing. The rules for read and write have been set to public as well. How should I recode the function that I am able to return the data from FireBase into the function and passed back to the caller?

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
Blender
  • 138
  • 8
  • 2
    Those are async functions, so you can't return from them when you "want". When your data is ready (first `return lessonList`), you can do whatever you want with your list (call another function, ...). – Stefan Golubović Mar 22 '18 at 16:49
  • 2
    When you call `firebaseCollect(key)`, your function is sending request to Firebase Database and returns immediately, i.e. your request is processed asynchronously. That's why you have callback functions (`onDataChanged`, `onCanceled`, ...), so that you can be notified when something happens or is done. – Stefan Golubović Mar 22 '18 at 16:59
  • @StefanGolubović Those comments sound like the start of a great answer! ;-) – Frank van Puffelen Mar 22 '18 at 17:27
  • @FrankvanPuffelen Well, I guess I should've posted the answer, but the idea was to give a quick hint why it's not working like [Blender](https://stackoverflow.com/users/9311761/blender) thought it would. In the meantime [Doug Stevenson](https://stackoverflow.com/users/807126/doug-stevenson) gave a great answer. :) – Stefan Golubović Mar 22 '18 at 18:18

2 Answers2

2

Firebase APIs are asynchronous. For your case, that means addValueEventListener returns immediately. Then, some time later, the listener you passed to it will be invoked with the data you're looking for. Your return statement in the callback doesn't actually return any data to the caller. In fact, you can't return anything from that callback. At the bottom of your function, when you return lessonList, you're actually returning an initially empty list to the caller, which may change later when the data finally arrives.

To get a better sense of how your code works, put log lines in various places, and see for yourself the order in which the code is invoked. You can read more about why Firebase APIs are asynchronous by reading this article. The bottom line is that you'll need to interact with the asynchronous APIs using asynchronous programming techniques. Don't try to make them synchronous.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
1

Data is loaded asynchronously from Firebase. Once the data is fetched the method onDatachange() is invoked.

You are returning lessonList inside onDatachange(). Return type of onDatachange() is void(Unit in kotlin). This is the reason for the type mismatch error.

For returning the result from the method onDatachange() try this.

Rissmon Suresh
  • 13,173
  • 5
  • 29
  • 38