Как дождаться пока цикл пройдет?

написал код:

val auth = FirebaseAuth.getInstance()
val database = FirebaseDatabase.getInstance()
val teachers = database.getReference("Teachers")
val students = database.getReference("Students")


fun takeClassesAndSetIt() {
    auth.currentUser?.uid?.let { id -> teachers.child(id).child("classes").get()
        .addOnCompleteListener {
            val counterClasses = it.result?.childrenCount?.toInt()!!
            val list = MutableList(1){ "_" }

            if (counterClasses > 0){
                for (i in 0 until counterClasses){
                    teachers.child(auth.currentUser?.uid!!).child("classes").child(i.toString()).child("number").get().addOnCompleteListener { res ->
                        list[i] = res.result?.value.toString()
                    }
                }
                println(list[0])
            }
        }
    }
}

После теста стало ясно что по необьяснимой причине строка println(list[0]) выполняется раньше, чем заканчивается цикл и выводит _ . Вопрос: можно ли заствавить программу ждать пока цикл полностью прокрутиться?


Ответы (1 шт):

Автор решения: Alex_Skvortsov

Создайте метод onFullCompletion вида:

fun onFullCompletion(list: List<String>) {
    println(list[0])
}

И измените свой код следующим образом:

fun takeClassesAndSetIt() {
    auth.currentUser?.uid?.let { id -> teachers.child(id).child("classes").get()
        .addOnCompleteListener {
            val counterClasses = it.result?.childrenCount?.toInt()!!
            val list = MutableList(1){ "_" }
            var completedCounter = 0

            if (counterClasses > 0){
                for (i in 0 until counterClasses){
                    teachers.child(auth.currentUser?.uid!!).child("classes").child(i.toString()).child("number").get().addOnCompleteListener { res ->
                        completedCounter++
                        list[i] = res.result?.value.toString()
                        if (completedCounter == counterClasses)
                            onFullCompletion(list)
                    }
                }
            }
        }
    }
}

Теперь код onFullCompletion будет вызываться только тогда, когда все данные получены.

Суть в том, что firebase получает данные через сеть, и они (данные) могут быть получены не в том порядке, в котором это ожидается в Вашем коде.

Заранее точно сказать, в каком порядке будут получены данные невозможно, поэтому в качестве решения имеет смысл создать счетчик и вызывать следующую функцию только тогда, когда счетчик сравнялся с ожидаемым количеством данных.

Уверен, что firebase предоставляет более правильные способы решения Вашей проблемы, но мне с ним работать почти не доводилось, а гуглить лень.

→ Ссылка