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

使用MVVM架构从Firebase获取数据时返回null问题排查

解决方案

1. 修复Firebase数据获取逻辑

你在FirebaseOrderService中调用db.collection("Order").document().get()时,无参的document()会生成一个新的空文档引用,而不是获取集合中已有的文档。这是核心问题,导致你拿到的是空文档,转换后返回null。

根据你原来的普通代码逻辑(取集合第一个文档),修改后的代码如下:

object FirebaseOrderService {
    private const val TAG = "FirebaseOrderService"
    suspend fun getOrderData(): Order? {
        val db = FirebaseFirestore.getInstance()
        return try {
            // 获取Order集合的所有文档,取第一个返回
            val querySnapshot = db.collection("Order").get().await()
            if (querySnapshot.documents.isNotEmpty()) {
                querySnapshot.documents[0].toOrder()
            } else {
                Log.w(TAG, "Order集合中无数据")
                null
            }
        } catch (e: Exception) {
            Log.e(TAG, "获取订单数据失败", e)
            FirebaseCrashlytics.getInstance().log("获取订单数据失败")
            FirebaseCrashlytics.getInstance().setCustomKey("id", "1")
            FirebaseCrashlytics.getInstance().recordException(e)
            null
        }
    }
}

如果你知道目标文档的ID,也可以直接指定文档ID获取:

// 替换成你的目标文档ID
db.collection("Order").document("your-document-id").get().await().toOrder()

2. 修正字段拼写与类型解析错误

  • 数据库中的字段是itemQuantity,但你的Order类中写成了itemQuantatiy(多了一个字母a),导致字段无法映射,触发空指针异常。
  • 数据库中itemPrice是Double类型(截图显示19.99),但代码中用getLong获取整数类型,会返回null,加上!!强制非空会直接抛出异常。
  • 建议不要用!!强制非空,改用?:提供默认值,避免转换失败。

修改后的Order.kt:

@Parcelize
data class Order(
    val id: String = "",
    val picUrl: String = "",
    val itemName: String = "",
    val itemPrice: Double = 0.0,
    val itemAmount: String = "",
    // 修正字段名拼写
    val itemQuantity: Int = 0
) : Parcelable {
    companion object {
        fun DocumentSnapshot.toOrder(): Order? {
            return try {
                val id = getString("id") ?: ""
                val picUrl = getString("picUrl") ?: ""
                val itemName = getString("itemName") ?: ""
                // 数据库中itemPrice是Double类型,改用getDouble获取
                val itemPrice = getDouble("itemPrice") ?: 0.0
                val itemAmount = getString("itemAmount") ?: ""
                // 修正字段名,用getLong转Int或直接用getInt
                val itemQuantity = getLong("itemQuantity")?.toInt() ?: 0

                Order(id, picUrl, itemName, itemPrice, itemAmount, itemQuantity)
            } catch (e: Exception) {
                Log.e(TAG, "转换订单数据失败", e)
                FirebaseCrashlytics.getInstance().log("转换订单数据失败")
                FirebaseCrashlytics.getInstance().setCustomKey("id", getString("id") ?: "unknown")
                FirebaseCrashlytics.getInstance().recordException(e)
                null
            }
        }
        private const val TAG = "Order"
    }
}

3. 优化ViewModel(可选)

将_orderList命名改为_order更符合语义,同时允许LiveData接收null值:

class SuccessShoppingViewModel: ViewModel() {
    private val _order = MutableLiveData<Order?>()
    val order: LiveData<Order?> = _order

    init {
        viewModelScope.launch {
            _order.value = FirebaseOrderService.getOrderData()
        }
    }
}

内容的提问来源于stack exchange,提问作者Ahmet Yılmaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 16:15:26