为什么Room数据库中保存的本地图片在重启应用后不显示?

Why local images saved in Room database are not displayed after i restart an app?

我将 uri 作为字符串保存在 Room 数据库中,然后应用程序检索数据并显示 LazyVerticalGrid 中的所有图像。当我添加图像时,一切正常,所有图像都正确显示。问题是当我重新启动应用程序时。所有图像都消失了,当我添加完全相同的图像(具有相同的 uri)时 - 它出现在第一个位置,但在我重新启动应用程序之前也出现在所有位置。当我检查日志时,所有 uri 也从数据库中以格式正确检索:

内容://com.android.providers.media.documents/document/image%3A9371

这是显示图像的代码(使用线圈):

@Composable
fun ProfilePhotoView(photo: String, navController: NavHostController) {
    Image(
        painter = rememberImagePainter(photo),
        contentDescription = null,
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .aspectRatio(1f)
            .padding(3.dp)
            .clip(RoundedCornerShape(10.dp))
            .clickable {},
        alignment = Alignment.Center
    )
    Log.i(TAG,"photo string = ${photo}")
}

这是我在添加到数据库之前检索 uri 的方式:

val selectImagelauncher = rememberLauncherForActivityResult(
        contract =
        ActivityResultContracts.GetContent()
    ) { uri: Uri? ->
        imageUriState = uri
    }
selectImagelauncher.launch("image/*")

你知道为什么在将相同图像添加到数据库之前我无法显示带有“旧”uri 的图像吗?

I'm saving uri's as a string in Room database

使用您现有的代码,那是行不通的。通常,you only have access rights to the content from within the activity that receives the Uri。一旦您的进程终止,所有访问权限都将丢失。

如果您将 ActivityResultContracts.GetContent() 更改为 ActivityResultContracts.OpenDocument(),并且您在 ContentResolver 上调用 takePersistableUriPermission() 以获得 Uri,那么您有很长的时间-term 访问内容。

创建你自己的 ActivityResultContract, 针对您的情况

contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
这是在拾取 Uri

之后
class GetPicturesContract : ActivityResultContract<String, Uri?>() {
override fun createIntent(context: Context, input: String?): Intent {
    return Intent(Intent.ACTION_OPEN_DOCUMENT)
        .addCategory(Intent.CATEGORY_OPENABLE)
        .setType(input)
}

override fun getSynchronousResult(
    context: Context,
    input: String
): SynchronousResult<Uri?>? {
    return null
}

override fun parseResult(resultCode: Int, intent: Intent?): Uri? {
    return if (intent == null || resultCode != Activity.RESULT_OK) null else intent.data
}

}