Локальные переменные не изменятся внутри OnCompleteListener - PullRequest
0 голосов
/ 20 сентября 2018

Здесь я пытаюсь получить всю необходимую информацию из базы данных и использовать ее для создания нового экземпляра учетной записи.Однако по какой-то причине после завершения части addOnCompleteListener значения name, username и т. Д. Не изменятся.Почему это так?

private fun initlAccount(uid:String):Account{
    var name = ""
    var username = ""
    var dob = ""
    var email = ""
    val friends = ArrayList<Account>()
    var tasks = ArrayList<Task>()
    db.collection("users").document(uid).get().addOnCompleteListener {
        if(it.isSuccessful){
            name = it.result.getString("Full name")!!
            username = it.result.getString("Username")!!
            dob = it.result.getString("Date of Birth")!!
            email = it.result.getString("Email")!!
            var arrtemp = it.result.get("Friends") as ArrayList<String>
            for(str in arrtemp){
                friends.add(initlAccount(str))
            }
            arrtemp = it.result.get("Tasks") as ArrayList<String>
            tasks = getTasks(arrtemp)
        }
    }
    val acc = Account(uid,username,name,dob,email,tasks,friends)
    println(acc.toString())
    return acc
}

Ответы [ 3 ]

0 голосов
/ 20 сентября 2018

Значения меняются , только если вы не ожидаете, что они

Измените сигнатуру метода так, чтобы она передавала обработчик завершений и ничего не возвращала

private fun initlAccount(uid:String, listener:OnCompleteListener) {

   ...

   db.collection("users").document(uid).get().addOnCompleteListener(listener)
}  // End of method

Переместите тело слушателя в место, где вы вызываете этот метод, что делает его «обратным вызовом» в другом потоке и, следовательно, «возвращает результаты выполнения»

Примечание: я не знаю Kotlin, но что-то вроде этого

initlAccount("uid-value", OnCompleteListener { it ->
    if(it.isSuccessful){
        val result = it.result

        name = result.getString("Full name")!!
        username = result.getString("Username")!!
        dob = result.getString("Date of Birth")!!
        email = result.getString("Email")!!
        var arrtemp = result.get("Friends") as ArrayList<String>
        for(str in arrtemp){
            friends.add(initlAccount(str)) // Note: This is recursive, and will be an issue
        }
        arrtemp = result.get("Tasks") as ArrayList<String>
        tasks = getTasks(arrtemp)
        val acc = Account(uid,username,name,dob,email,tasks,friends)
        println(acc.toString())

        // Your account is returned here, so you can update a UI element, for example
    }
}) // end initlAccount method call

// do NOT use acc here, it will be unassigned or null 

И я вижу, что вы делаете рекурсивный вызов, поэтому вы должны либо обработать запрос к базе данных, чтобы сам клиент не находился в бесконечном цикле («дружба» должна быть рефлексивной - userA являетсядруг userB, поэтому получение учетной записи userB вернется к получению друзей userA и продолжится), или вы можете попробовать исследовать операторы RxJava / Kotlin flatMap.

0 голосов
/ 21 сентября 2018

Вместо создания метода, который возвращает Account.

Почему бы не выполнить запрос напрямую для получения Account?потому что это приводит к несинхронизированному рабочему процессу.

   db.collection("users").document(uid).get().addOnCompleteListener {
        if(it.isSuccessful){
            name = it.result.getString("Full name")!!
            username = it.result.getString("Username")!!
            dob = it.result.getString("Date of Birth")!!
            email = it.result.getString("Email")!!
            var arrtemp = it.result.get("Friends") as ArrayList<String>
            for(str in arrtemp){
                friends.add(initlAccount(str))
            }
            arrtemp = it.result.get("Tasks") as ArrayList<String>
            tasks = getTasks(arrtemp)

            val acc = Account(uid,username,name,dob,email,tasks,friends)
            println(acc.toString())
            // Probably do a save in Database?
        }
    }
0 голосов
/ 20 сентября 2018
val acc = Account(uid,username,name,dob,email,tasks,friends)
println(acc.toString())
return acc

этот код выполняется перед кодом внутри onCompleteListener.Вы должны создать Account внутри слушателя завершения.Конечно, вы не можете вернуться изнутри слушателя, поэтому вместо * local укажите val acc как переменную-член.Я не знаю ваш полный код, поэтому не могу дать много предложений относительно этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...