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

Firestore写入正常但无法读取数据且无报错问题求助

Firestore异步读取数据为空问题修复

问题现象

  • Firestore数据写入功能正常运行
  • 参考官方文档编写的读取代码全程无报错、不触发失败回调,但无法获取到任何数据
  • 调用读取方法后立刻获取数据列表为空,RecyclerView无法展示内容

问题代码

Fragment 实现

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    init()
}

private fun init() {
    db = FirebaseFirestore.getInstance()
    mFirestoreRef = db.collection("users").document(USER_ID).collection("deals")
    val viewModel = ViewModelProvider(this).get(DealsViewModel::class.java)
    viewModel.retriveData(mFirestoreRef)
    recyclerView = binding.rcView
    adapter = TradeNoteAdapter()
    recyclerView.adapter = adapter
    var notes = viewModel.getAllNotes()
    adapter.setList(notes)
}

ViewModel 实现

import android.widget.Toast
import androidx.lifecycle.ViewModel
import com.google.firebase.firestore.CollectionReference
import space.timur.tradenotefirebase.APP
import space.timur.tradenotefirebase.model.TradeNoteModel

class DealsViewModel : ViewModel() {

private var notes: ArrayList<TradeNoteModel> = ArrayList()

fun retriveData(firestoreReference: CollectionReference){
    firestoreReference.get()
        .addOnSuccessListener { documents ->
            for(document in documents){
                var note = document.toObject(TradeNoteModel::class.java)
                notes.add(note)
            }
        }.addOnFailureListener{ e->
            Toast.makeText(APP, e.message, Toast.LENGTH_SHORT).show()
        }
}

fun getAllNotes(): ArrayList<TradeNoteModel> {
    return notes
}

}

问题根因

Firestore的get()方法是异步网络请求,调用后不会阻塞当前线程等待结果返回。你在调用retriveData()后立刻执行getAllNotes()时,请求还在网络传输阶段,notes列表还没被写入数据,自然是空的。等后续addOnSuccessListener回调执行、往notes里添加数据时,你早就把空列表传给了适配器,也没有通知适配器数据更新,所以RecyclerView一直显示空白。

修复方案

使用LiveData持有加载完成的数据,让Fragment观察数据变化,数据拉取完成后自动刷新UI:

修正后的ViewModel

import android.widget.Toast
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.google.firebase.firestore.CollectionReference
import space.timur.tradenotefirebase.APP
import space.timur.tradenotefirebase.model.TradeNoteModel

class DealsViewModel : ViewModel() {

    private val _notes = MutableLiveData<List<TradeNoteModel>>()
    val notes: LiveData<List<TradeNoteModel>> = _notes

    fun retriveData(firestoreReference: CollectionReference){
        firestoreReference.get()
            .addOnSuccessListener { documents ->
                val noteList = arrayListOf<TradeNoteModel>()
                for(document in documents){
                    val note = document.toObject(TradeNoteModel::class.java)
                    noteList.add(note)
                }
                // 数据加载完成后发送到LiveData
                _notes.postValue(noteList)
            }.addOnFailureListener{ e->
                Toast.makeText(APP, e.message, Toast.LENGTH_SHORT).show()
            }
    }
}

修正后的Fragment初始化逻辑

private fun init() {
    db = FirebaseFirestore.getInstance()
    mFirestoreRef = db.collection("users").document(USER_ID).collection("deals")
    val viewModel = ViewModelProvider(this).get(DealsViewModel::class.java)
    recyclerView = binding.rcView
    adapter = TradeNoteAdapter()
    recyclerView.adapter = adapter

    // 观察数据变化,数据加载完成后自动刷新列表
    viewModel.notes.observe(viewLifecycleOwner) { noteList ->
        adapter.setList(noteList)
    }

    // 触发数据拉取
    viewModel.retriveData(mFirestoreRef)
}

注意:如果不使用LiveData,也可以直接在addOnSuccessListener回调中拿到数据后更新适配器,但绝对不能在异步请求刚发起时同步读取结果,Firestore所有网络操作默认都是异步执行的,不会立刻返回结果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 03:24:27