Kotlin中如何获取异步lambda回调内部赋值的变量值
问题核心原因
Firebase Realtime Database的get()操作是异步执行的,addOnSuccessListener的回调会在网络请求完成后才执行,而你当前写的方法是同步返回,执行到return语句时回调还没触发,所以拿到的永远是初始值0.0f。
解决方案
方案1:使用自定义回调(兼容Java环境,无需额外依赖)
把方法从同步返回改为传入回调参数,计算完成后通过回调返回结果:
private fun get_rating2(review: String, onResult: (Float) -> Unit) { val reviewref = RTDBref.child(review) val ratinglist = arrayListOf<Int>() reviewref.get().addOnSuccessListener { reviewsnap -> reviewsnap.children.forEach { ratingsnap -> val rating = ratingsnap.child("rating").getValue<Int>() ratinglist.add(rating!!) } val average_rating = ratinglist.average().toFloat() // 计算完成后调用回调返回结果 onResult(average_rating) }.addOnFailureListener { // 异常场景可自定义返回默认值 onResult(0.0f) } }
调用方式:
get_rating2("你的review参数") { averageRating -> // 在此处使用返回的平均评分执行后续逻辑 Log.d("评分结果", "平均评分:$averageRating") }
方案2:使用Kotlin协程(Kotlin生态推荐写法)
利用kotlinx-coroutines-play-services库的await()扩展方法,把异步回调转成挂起函数,代码逻辑更简洁:
首先需要在模块build.gradle中添加依赖:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.7.3"
方法实现:
private suspend fun get_rating2(review: String): Float { val reviewref = RTDBref.child(review) val ratinglist = arrayListOf<Int>() // await()会挂起协程,直到请求完成返回结果,不会阻塞主线程 val reviewsnap = reviewref.get().await() reviewsnap.children.forEach { ratingsnap -> val rating = ratingsnap.child("rating").getValue<Int>() ratinglist.add(rating!!) } return ratinglist.average().toFloat() }
调用方式:在对应作用域的协程中调用即可
// Activity中使用lifecycleScope,ViewModel中使用viewModelScope lifecycleScope.launch { val averageRating = get_rating2("你的review参数") // 在此处使用评分执行后续逻辑 }
方案3:同步阻塞获取(不推荐,仅特殊场景使用)
如果必须要求同步返回结果,可以用CountDownLatch阻塞线程等待回调执行完成,禁止在主线程调用,会导致界面卡顿ANR:
private fun get_rating2(review: String): Float { val reviewref = RTDBref.child(review) val ratinglist = arrayListOf<Int>() val latch = CountDownLatch(1) var average_rating = 0.0f reviewref.get().addOnSuccessListener { reviewsnap -> reviewsnap.children.forEach { ratingsnap -> val rating = ratingsnap.child("rating").getValue<Int>() ratinglist.add(rating!!) } average_rating = ratinglist.average().toFloat() latch.countDown() }.addOnFailureListener { latch.countDown() } // 阻塞等待回调执行完成 latch.await() return average_rating }
内容的提问来源于stack exchange,提问作者sooyeon
相关产品推荐
相关产品推荐

