【问题标题】:Data from Firebase Realtime Database is retreived, but not set when returned from a function?检索 Firebase 实时数据库中的数据,但从函数返回时未设置?
【发布时间】:2022-01-25 16:50:01
【问题描述】:

我正在尝试从 Firebase 获取数据并将其作为数组返回。到目前为止,这是可行的,但是数据仍然是我设置的默认数据。

这是代码(我添加了一些 cmets 以阐明它在哪里工作以及 id 在哪里不工作):

fun getRandomQuestion() : ArrayList<ArrayList<String>>{
    val random = Random(1234567)
    val randQuestionId = random.nextInt(0, 27)

    var dataRequestResult : String = "empty"

    var requestSide1 : String = "empty"
    var requestSide2 : String = "empty"
    var requestCount1 : String = "empty"
    var requestCount2 : String = "empty"

    //Get a random question from the DB
    Firebase.database.reference.child(Constants.wyrDBQuestionLocation)
        .child(randQuestionId.toString())
        .get()
        .addOnFailureListener { task ->
            Log.i("Get WYR Question Status", "Failed: " + task.message.toString())
            requestSide1 = "empty"
            requestSide2 = "empty"
            requestCount1 = "empty"
            requestCount2 = "empty"
        }.addOnSuccessListener {
            Log.i("Get WYR Question Status", "Success")

            //Logging this data returns the correct information from firebase, no issue here
            Log.i("Request Data Result", it.value.toString())

            dataRequestResult = it.value.toString()
        }

    requestSide1 = dataRequestResult.substringAfter("side1Question=").substringBefore("}")
    requestSide2 = dataRequestResult.substringAfter("side2Question=").substringBefore(",")
    requestCount1 = dataRequestResult.substringAfter("sideCount1=").substringBefore(",")
    requestCount2 = dataRequestResult.substringAfter("sideCount2=").substringBefore(",")

    //Return the value
    return arrayListOf(arrayListOf(requestSide1, requestCount1), arrayListOf(requestSide2, requestCount2))
}

我尝试获取返回值的活动:

    val myQuestion = databaseController.getRandomQuestion()

    //This is where the issue lies
    //When I get the returned data from the function above, it gives me all of the defaults I had set in the function (which is "empty")
    //It logs:`[["empty", "empty"],["empty", "empty"]]`
    Log.i("My Question", myQuestion.toString())

成功监听中的数据是正确的,但是返回值还是默认的。 这是日志的图像:

“请求日志结果”,不介意结果,我在做一个WYR应用。

我注意到来自侦听器的请求是最后一个,而不是第一个

我认为这与尚未完全收集的数据有关,因为在我制作的另一个应用程序中,我所要做的就是给它一个延迟并且它会被设置,但在这种情况下,我不知道怎么办。

任何帮助将不胜感激! :)

【问题讨论】:

标签: android firebase kotlin firebase-realtime-database kotlin-coroutines


【解决方案1】:

这是我的解决方案

方法一

fun getRandomQuestion() : ArrayList<ArrayList<String>>{
    val random = Random(1234567)
    val randQuestionId = random.nextInt(0, 27)

    var dataRequestResult : String = "empty"

    var requestSide1 : String = "empty"
    var requestSide2 : String = "empty"
    var requestCount1 : String = "empty"
    var requestCount2 : String = "empty"

    //Get a random question from the DB
    Firebase.database.reference.child(Constants.wyrDBQuestionLocation)
        .child(randQuestionId.toString())
        .get()
        .addOnFailureListener { task ->
            Log.i("Get WYR Question Status", "Failed: " + task.message.toString())
            requestSide1 = "empty"
            requestSide2 = "empty"
            requestCount1 = "empty"
            requestCount2 = "empty"
        }.addOnSuccessListener {
            Log.i("Get WYR Question Status", "Success")

            //Logging this data returns the correct information from firebase, no issue here
            Log.i("Request Data Result", it.value.toString())

            dataRequestResult = it.value.toString()
    requestSide1 = dataRequestResult.substringAfter("side1Question=").substringBefore("}")
    requestSide2 = dataRequestResult.substringAfter("side2Question=").substringBefore(",")
    requestCount1 = dataRequestResult.substringAfter("sideCount1=").substringBefore(",")
    requestCount2 = dataRequestResult.substringAfter("sideCount2=").substringBefore(",")

        }

    
    //Return the value
    return arrayListOf(arrayListOf(requestSide1, requestCount1), arrayListOf(requestSide2, requestCount2))
}

方法二

fun getRandomQuestion() : ArrayList<ArrayList<String>>{
    val random = Random(1234567)
    val randQuestionId = random.nextInt(0, 27)

    var dataRequestResult : String = "empty"

    var requestSide1 : String = "empty"
    var requestSide2 : String = "empty"
    var requestCount1 : String = "empty"
    var requestCount2 : String = "empty"

    //Get a random question from the DB
    Firebase.database.reference.child(Constants.wyrDBQuestionLocation)
        .child(randQuestionId.toString())
        .get()
        .addOnFailureListener { task ->
            Log.i("Get WYR Question Status", "Failed: " + task.message.toString())
            requestSide1 = "empty"
            requestSide2 = "empty"
            requestCount1 = "empty"
            requestCount2 = "empty"
        }.addOnSuccessListener {
            Log.i("Get WYR Question Status", "Success")

            //Logging this data returns the correct information from firebase, no issue here
            Log.i("Request Data Result", it.value.toString())

            dataRequestResult = it.value.toString()
    requestSide1 = dataRequestResult.substringAfter("side1Question=").substringBefore("}")
    requestSide2 = dataRequestResult.substringAfter("side2Question=").substringBefore(",")
    requestCount1 = dataRequestResult.substringAfter("sideCount1=").substringBefore(",")
    requestCount2 = dataRequestResult.substringAfter("sideCount2=").substringBefore(",")
//Return the value
    return arrayListOf(arrayListOf(requestSide1, requestCount1), arrayListOf(requestSide2, requestCount2))
        }

return null    
    
}

【讨论】:

  • 你测试你的方法了吗?在第一种方法中,结果似乎与 OP 问题中的结果相同。而第二种方法有一个错误,你不能从中返回null,因为函数返回non-nullable类型fun getRandomQuestion() : ArrayList&lt;ArrayList&lt;String&gt;&gt;。你的方法行不通。
  • 这甚至不会编译,即使编译了,它也有与原始帖子相同的错误。
【解决方案2】:

您在请求数据库数据时使用的侦听器将在getRandomQuestion 函数返回ArrayList 之后触发。您可以使用Kotlin coroutines 处理回调并暂停协程直到回调被触发,例如:

suspend fun getRandomQuestion() = suspendCoroutine<String> { continuation ->
    Firebase.database.reference.child(Constants.wyrDBQuestionLocation)
    .child(randQuestionId.toString())
    .get()
    .addOnFailureListener { task ->
        continuation.resume("empty")
    }.addOnSuccessListener {
        continuation.resume(it.value.toString())
    }
}

// somewhere in your code (e.g. in ViewModel, Activity or Fragment):

someCoroutineScope.launch {
    val question: String = getRandomQuestion();
    // ... use question to update UI
}

ActivityFragment 中,您可以使用lifecycleScope,在ViewModel - viewModelScope

suspendCoroutine builder 函数用于等待回调。 suspendCoroutine 暂停执行协程,直到我们决定通过调用适当的方法继续 - Continuation.resume...

【讨论】:

    猜你喜欢
    • 2019-04-16
    • 2020-12-09
    • 1970-01-01
    • 2021-02-06
    • 2017-10-06
    • 1970-01-01
    • 2018-09-11
    • 2019-02-04
    • 2019-05-30
    相关资源
    最近更新 更多