You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin接入Firebase监听数值时while循环条件为假仍不终止问题

问题根因
  • 协程while循环中传入checkGsValue的gLt参数,是onDataChange触发瞬间从Firebase拿到的快照值,属于该次回调的局部变量。后续Firebase的gLvl字段更新后,只会触发新的onDataChange回调,已经启动的协程里的gLt不会同步更新,所以只要首次拿到的gLt>250,循环判断条件永远为真,不会退出。
  • 每次onDataChange触发都会启动一个新的协程,旧协程不会被自动取消,会一直在后台轮询打印日志,会造成内存泄露和性能损耗。
修复方案

方案1:移除自定义轮询,直接用Firebase原生回调

Firebase的addValueEventListener本身就会在数值变化时自动触发回调,完全不需要额外写while循环轮询,直接在回调中处理逻辑即可:

private var gLTF: Boolean? = null

myRef.addValueEventListener(object : ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
        val gsLvlR = dataSnapshot.child("gLvl").value.toString()
        val gLt = gsLvlR.toInt()
        gLTF = gLt > 250
        if (gLTF == true) {
            println("true")
            // 符合条件时的业务逻辑
        } else {
            println("false")
            // 不符合条件时的业务逻辑
        }
    }

    override fun onCancelled(error: DatabaseError) {
        // 读取失败处理逻辑
    }
})

方案2:如果确实需要定时执行任务

如果你的业务场景需要每15秒执行一次任务,同时要判断最新的gLvl值,可以把最新数值存在全局变量,同时管理协程的生命周期:

private var latestGLt: Int? = null
private var pollingJob: Job? = null
private var gLTF: Boolean? = null

myRef.addValueEventListener(object : ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
        val gsLvlR = dataSnapshot.child("gLvl").value.toString()
        // 更新全局存储的最新值
        latestGLt = gsLvlR.toInt()
        // 取消之前的轮询协程,避免重复启动
        pollingJob?.cancel()
        // 启动新的轮询协程
        pollingJob = CoroutineScope(Dispatchers.Default).launch {
            while (latestGLt?.let { checkGsValue(it) } == true) {
                println("true")
                delay(15000)
                // 每次循环都读取最新的全局值判断
                if (latestGLt?.let { checkGsValue(it) } == false) {
                    println("false")
                    break
                }
            }
        }
    }

    override fun onCancelled(error: DatabaseError) {
        // 读取失败处理逻辑
        pollingJob?.cancel()
    }
})

fun checkGsValue(gL: Int): Boolean {
    gLTF = gL > 250
    return gLTF as Boolean
}

内容的提问来源于stack exchange,提问作者Xavi Bw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 12:24:00