从 Uri 获取图像并显示在与 ViewModel 的可组合项中

Get image from Uri and show in composable with ViewModel

我有一个过去工作正常的可组合项,但现在在一些库更新后它就不能工作了。
我正在使用 ViewModel 保存从 ActivityResultContracts.TakePicture() 编辑的图像 return 并将其显示在 Box.
中的 ImagePhotoButton 可组合项工作正常,return 正确图像 url,但我的主要可组合项中的图像字符串始终为 null。

SamplePage.kt

@Composable
fun SamplePage(navController: NavController) {

    val inputViewModel = InputViewModel()
    val context = LocalContext.current

    Column{
        InputFields(inputViewModel, navController, setPerm)
    }
}

@Composable
fun InputFields(inputViewModel: InputViewModel, navController: NavController) {
    val image: String by inputViewModel.image.observeAsState("")

    Column() {
        Row(verticalAlignment = Alignment.CenterVertically) {
            Box(contentAlignment = Alignment.Center) {
                val painter = rememberImagePainter(data = image)
                Image(
                    painter = painter,
                    contentScale = ContentScale.FillWidth,
                    contentDescription = null
                )
                if (painter.state !is ImagePainter.State.Success) {
                    Icon(
                        painter = painterResource(id = R.drawable.icon),
                        contentDescription = null
                    )
                }
            }
            PhotoButton() {
                inputViewModel.onImageChange(it)
            }
        }
    }
}

class InputViewModel : ViewModel() {
    private val _image: MutableLiveData<String> = MutableLiveData("")
    val image: LiveData<String> = _image

    fun onImageChange(newImage: String) {
        _image.value = newImage
    }
}

PhotoButton.kt

@Composable
fun PhotoButton(onValChange: ((String) -> Unit)?){
    val context = LocalContext.current
    val storageDir: File? = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
    val file = File(storageDir, "picFromCamera")
    val uri = FileProvider.getUriForFile(
        context,
        context.packageName.toString() + ".provider",
        file
    )

    val launcher = rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) {
        if (onValChange != null) {
            onValChange(uri.toString())
        }
    }

    FAB() {
        launcher.launch(uri)
    }
}

您正在为每个重组创建一个新的视图模型:

val inputViewModel = InputViewModel()

相反,您应该使用 viewModel():它将在第一次调用时创建一个新的视图模型,并存储它以供将来调用:

val inputViewModel = viewModel<InputViewModel>()

查看有关在撰写状态下使用视图模型的更多信息documentation