如何让Kotlin函数等待Firestore数据库获取数据后再返回结果
解决Firestore异步获取数据返回空列表的问题
你遇到的问题根源在于Firestore的get()是异步操作,原代码里的addOnSuccessListener会在后台线程执行,而函数会直接跳过回调逻辑提前返回空的exercisesList。用.await()结合Kotlin协程可以让函数等待数据获取完成后再返回结果,具体修改如下:
修改后的代码
import kotlinx.coroutines.tasks.await import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext suspend fun getExercise(bodyPart: String): MutableList<String> { val db = Firebase.firestore val exercisesList = mutableListOf<String>() return try { // 构建查询并使用.await()等待结果返回 val queryResult = db.collection("exercises") .whereEqualTo("body-part", bodyPart) .get() .await() // 遍历结果填充列表 for (doc in queryResult) { exercisesList.add(doc.id) Log.d(TAG, "${doc.id} => ${doc.data}") } exercisesList } catch (exception: Exception) { // 捕获查询异常并打印日志 Log.w(TAG, "Error getting documents: ", exception) // 异常时返回空列表,也可根据需求抛出异常 exercisesList } }
关键修改说明
- 给函数添加
suspend修饰符:.await()是挂起函数,只能在挂起函数或协程作用域内调用,所以必须给getExercise加上该修饰符。 - 用
.await()替代回调:query.get().await()会让协程暂停,直到Firestore返回查询结果,避免函数提前返回空列表。 - 用
try-catch处理异常:替代原代码的addOnFailureListener,统一捕获查询过程中可能出现的错误。 - (可选)IO线程执行:如果希望数据库操作不阻塞主线程,可以把逻辑包裹在
withContext(Dispatchers.IO)中:suspend fun getExercise(bodyPart: String): MutableList<String> { val db = Firebase.firestore return withContext(Dispatchers.IO) { val exercisesList = mutableListOf<String>() try { val queryResult = db.collection("exercises") .whereEqualTo("body-part", bodyPart) .get() .await() for (doc in queryResult) { exercisesList.add(doc.id) Log.d(TAG, "${doc.id} => ${doc.data}") } } catch (exception: Exception) { Log.w(TAG, "Error getting documents: ", exception) } exercisesList } }
调用注意事项
因为这是挂起函数,不能直接在普通非挂起函数中调用,需要在协程作用域内执行,比如:
// 在Activity/Fragment中使用lifecycleScope lifecycleScope.launch { val chestExercises = getExercise("chest") // 在此处使用获取到的训练列表 } // 在ViewModel中使用viewModelScope viewModelScope.launch { val legExercises = getExercise("legs") // 更新UI或处理数据 }
内容的提问来源于stack exchange,提问作者SatanasHammer
相关产品推荐
相关产品推荐

