Return 没有返回值

Return is not returning the value

所以我的视图模型的 return 函数没有给出 return 预期给出 return 位图的地方所以它可以在 UI 中使用设置图像。

视图模型代码:

    val bitmap : MutableLiveData<Bitmap> by lazy { MutableLiveData<Bitmap>() }

    fun retrive(doc_name : String,uid: String){
    viewModelScope.launch(Dispatchers.IO){
         bitmap.postValue(repository.retrive(doc_name,uid))
     }
   }

存储库代码:

var localfile = createTempFile("tempImage", null)
var bitmap :Bitmap? = null
override suspend fun retrive(doc_name:String,uid: String)  : Bitmap?{
    val storageRef = FirebaseStorage.getInstance().reference?.child("/image/8WEFQnomCEMtlaSkCIkrBgT7XeO2/download")

    storageRef.getFile(localfile).addOnSuccessListener {
        bitmap = BitmapFactory.decodeFile(localfile.absolutePath)
    }
    return bitmap
}

View Created 部分的 Fragment 中的代码:

val obsover = Observer<Bitmap>{
        image.setImageBitmap(it)
    }
    admin_viewmodel.bitmap.observe(viewLifecycleOwner,obsover)

因为我在我的 Repository 函数中保留了位图可以为 null 的信息,所以它在图像视图中打开了没有图像的片段 但是如果我保持 Bitmap 不为 null(!!) 应用程序崩溃并在下面的行中给出 Null Pointer Exception 错误:

  1. 在我上面分享的存储库代码中:

         return bitmap!!
    

2.Inside我上面分享的View Model代码:

bitmap.postValue(repository.retrive(doc_name,uid))

我认为它无法 return 因为事情在不同的线程上工作。 请帮我解决这个问题,谢谢。

Broot 回复代码更改后编辑:

override suspend fun retrive(doc_name:String,uid: String)  : Bitmap {
return suspendCoroutine { cont ->
    val storageRef =
        FirebaseStorage.getInstance().reference?.child("/image/0XhL4jD4XCemk38rcRkIEjJMgjh2/Aadhar")
    val localfile = createTempFile("tempImage", null)
    storageRef.getFile(localfile).addOnSuccessListener {
        val x = cont.resume(bitmap!!)
        Log.d("checck", "$x")
    }


}

}

您的原始代码不正确,因为它触发了 API 的异步函数,然后立即 returns,在异步工作完成并触发其回调以更新 bitmap 属性.

你的第二个代码是错误的,因为它试图用 属性 bitmap 的值恢复继续,你还没有用回调中返回的值更新它。此外,由于您只需要来自云文件的位图,因此没有理由将其下载到临时文件中。您可以直接使用字节。而且没有理由使用我可以看到的 属性 。 bitmap 可以是局部变量。

此外,由于在失败的情况下您不执行任何操作,因此如果从 Firebase 检索数据时出现问题,您的函数将挂起。下面,我只是抛出错误,但如果你愿意,你可以做一些不同的事情,比如返回 null。

我不知道你用这两个参数做什么,但我把它们留下了。我让你来决定你的字节限制应该是多少(我只使用了 500 万字节)。我不记得保证的最小可用内存量是针对 Android 应用程序的,而且您可能知道您正在检索的文件无论如何都低于该值。

override suspend fun retrive(doc_name: String, uid: String): Bitmap = suspendCoroutine { cont ->
    val storageRef =
        FirebaseStorage.getInstance().reference.child("/image/0XhL4jD4XCemk38rcRkIEjJMgjh2/Aadhar")
    storageRef.getBytes(5_000_000L).addOnSuccessListener { byteArray ->
        val bitmap = BitmapFactory.decodeByteArray(byteArray)
        cont.resume(bitmap)
    }.addOnFailureListener {
        cont.resumeWithException(it)
    }
}

但是: Firebase 已经带有 await() 扩展暂停功能,因此您不必使用 suspendCoroutine.

override suspend fun retrive(doc_name: String, uid: String): Bitmap {
    val storageRef =
        FirebaseStorage.getInstance().reference.child("/image/0XhL4jD4XCemk38rcRkIEjJMgjh2/Aadhar")
    val byteArray = storageRef.getBytes(5_000_000L).await()
    return BitmapFactory.decodeByteArray(byteArray)
}

由于解码位图是一项繁重的操作,我会在 Dispatchers.Default:

中执行此操作
override suspend fun retrive(doc_name: String, uid: String): Bitmap = withContext(Dispatchers.Default) {
    val storageRef =
        FirebaseStorage.getInstance().reference.child("/image/0XhL4jD4XCemk38rcRkIEjJMgjh2/Aadhar")
    val byteArray = storageRef.getBytes(5_000_000L).await()
    return BitmapFactory.decodeByteArray(byteArray)
}