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

无法将Firestore数据传递至Kotlin对象属性的技术求助

问题根源

你的代码无法获取数据的核心原因是:Firestore的get()是异步网络请求,init块里发起请求后,程序不会等待请求完成就继续执行后续代码。当你在另一个Activity创建CardsFromFirebase实例并直接访问decoded_card1时,addOnSuccessListener还没执行,lateinit变量根本没被初始化,自然拿不到数据。

解决方案

下面提供两种可行的修改方案,解决异步数据加载的问题:

方案1:使用回调接口处理异步结果

修改CardsFromFirebase类,通过回调通知数据加载完成:

class CardsFromFirebase {
    var decoded_card1: Bitmap? = null

    // 定义回调接口,用于通知数据加载状态
    interface OnCardLoadedListener {
        fun onLoaded(bitmap: Bitmap)
        fun onFailed(error: Exception)
    }

    // 封装数据加载方法
    fun loadCard(listener: OnCardLoadedListener) {
        Firebase.firestore.collection("Cards")
            .document("albus")
            .get()
            .addOnSuccessListener { document ->
                val base64 = document.data!!["resim"].toString()
                val imageBytes = Base64.decode(base64, Base64.DEFAULT)
                decoded_card1 = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
                decoded_card1?.let { listener.onLoaded(it) }
            }
            .addOnFailureListener { error ->
                listener.onFailed(error)
            }
    }
}

在Activity中调用,等待回调完成后再使用数据:

val card = CardsFromFirebase()
card.loadCard(object : CardsFromFirebase.OnCardLoadedListener {
    override fun onLoaded(bitmap: Bitmap) {
        // 数据加载完成后再赋值
        card1 = bitmap
        card2 = bitmap
        // 如果需要更新UI,必须在主线程执行
        runOnUiThread {
            // 比如设置ImageView的图片:imageView.setImageBitmap(bitmap)
        }
    }

    override fun onFailed(error: Exception) {
        // 处理加载失败的情况,比如打印错误或提示用户
        error.printStackTrace()
    }
})

方案2:使用Kotlin协程简化异步逻辑

如果项目支持协程,这种方式代码更简洁:
修改CardsFromFirebase类:

import kotlinx.coroutines.tasks.await

class CardsFromFirebase {
    var decoded_card1: Bitmap? = null

    // 用suspend关键字标记挂起函数
    suspend fun loadCardData() {
        try {
            // 使用await()等待异步请求完成
            val document = Firebase.firestore.collection("Cards")
                .document("albus")
                .get()
                .await()
            
            val base64 = document.data!!["resim"].toString()
            val imageBytes = Base64.decode(base64, Base64.DEFAULT)
            decoded_card1 = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
        } catch (e: Exception) {
            e.printStackTrace()
            throw e // 抛出异常让调用方处理
        }
    }
}

在Activity的协程作用域中调用:

import androidx.lifecycle.lifecycleScope

// 在Activity中
lifecycleScope.launch {
    val card = CardsFromFirebase()
    try {
        card.loadCardData()
        card.decoded_card1?.let {
            card1 = it
            card2 = it
            // 这里可以直接更新UI,因为lifecycleScope默认在主线程
        }
    } catch (e: Exception) {
        // 处理加载失败
    }
}
额外提示
  • 不要用lateinit存储异步加载的变量:无法保证它一定会被初始化,容易抛出UninitializedPropertyAccessException,改用可空类型Bitmap?更安全。
  • 处理空值:document.data!!存在空指针风险,建议先判断document.exists()再获取数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 15:40:28