使用Kotlin Coroutines从Firestore获取数据为空问题求助
排查Kotlin协程从Firestore获取数据为空的问题
我在使用Kotlin Coroutines从Firestore获取数据时,Log.d("Products", products.toString())返回空值,通过Toast查看结果数量显示为0,且Logcat无任何错误信息。以下是我的代码及Firestore结构,恳请帮忙排查原因:
SearchItemActivity代码
import android.os.Bundle import android.util.Log import android.widget.GridView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.google.firebase.Firebase import com.google.firebase.firestore.DocumentSnapshot import com.google.firebase.firestore.firestore import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.tasks.await class SearchItemActivity : AppCompatActivity() { private val db = Firebase.firestore private val products: MutableList<DocumentSnapshot> = mutableListOf() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_search_item) val gridView = findViewById<GridView>(R.id.itemGridView) CoroutineScope(Dispatchers.Main).launch { try { val result = db.collection("product").get().await() Toast.makeText(this@SearchItemActivity, "Number of documents in 'product' collection: ${result.size()}", Toast.LENGTH_SHORT).show() for (document in result) { val uid = document.id val results = db.collection("product").document(uid).collection("products").get().await() products.addAll(results.documents) } val adapter = ItemUserAdapter(this@SearchItemActivity, layoutInflater, products) gridView.adapter = adapter } catch (e: Exception) { Toast.makeText(this@SearchItemActivity, e.localizedMessage, Toast.LENGTH_SHORT).show() } } Log.d("Products", products.toString()) gridView.setOnItemClickListener { parent, view, position, id -> val product = parent.getItemAtPosition(position) as DocumentSnapshot Toast.makeText(applicationContext, "UID: ${product.id}", Toast.LENGTH_SHORT).show() } } }
Firestore结构
- 集合内的子集合:

- Products内部结构:

问题排查与解决方案
1. 异步执行顺序问题
当前Log.d("Products", products.toString())在协程启动后立即执行,而Firestore请求是异步操作,此时products还未被填充,导致日志为空。将Log语句移到协程内部、数据填充完成之后:
CoroutineScope(Dispatchers.Main).launch { try { val result = db.collection("product").get().await() Toast.makeText(this@SearchItemActivity, "Number of documents in 'product' collection: ${result.size()}", Toast.LENGTH_SHORT).show() for (document in result) { val uid = document.id val results = db.collection("product").document(uid).collection("products").get().await() products.addAll(results.documents) } // 移至此处打印日志 Log.d("Products", products.toString()) val adapter = ItemUserAdapter(this@SearchItemActivity, layoutInflater, products) gridView.adapter = adapter } catch (e: Exception) { Toast.makeText(this@SearchItemActivity, e.localizedMessage, Toast.LENGTH_SHORT).show() } }
2. Firestore集合路径不匹配(核心问题)
从截图可见,根集合是Projects,但代码中使用的是db.collection("product"),路径完全不匹配:
- 截图根集合为Projects,而非
product - 每个
Projects文档下的子集合是products
修正集合路径:
// 将db.collection("product")改为db.collection("Projects") val result = db.collection("Projects").get().await() for (document in result) { val uid = document.id // 子集合路径对应Projects/{docId}/products val results = db.collection("Projects").document(uid).collection("products").get().await() products.addAll(results.documents) }
3. 隐性权限问题
若路径修正后仍无数据,检查Firestore安全规则。默认规则仅允许认证用户读取,未登录时请求会静默失败(无错误日志)。可临时修改规则测试:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if true; // 测试用,上线需恢复安全规则 } } }
4. 协程作用域优化
建议使用lifecycleScope替代手动创建的CoroutineScope(Dispatchers.Main),避免内存泄漏:
// 需先导入依赖:implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2" lifecycleScope.launch { // 内部代码保持不变 }
内容的提问来源于stack exchange,提问作者Ajay Satpati
相关产品推荐
相关产品推荐

