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
相关产品推荐
相关产品推荐

