无法将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
相关产品推荐
相关产品推荐

