【问题标题】:Why local images saved in Room database are not displayed after i restart an app?为什么我重新启动应用程序后不显示保存在 Room 数据库中的本地图像?
【发布时间】:2021-12-19 12:42:36
【问题描述】:

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

content://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 的图像吗?

【问题讨论】:

  • %3A 是一个编码字符,你确定你解码正确吗?
  • 我相信我会这样做,因为在我重新启动应用程序之前,每个图像都会正确显示
  • 另外,当我从图库而不是文档中检索数据时,格式为:content://media/external/images/media/9323 并且没有任何变化
  • 在存储之前它可能没有被编码。您是否调试以检查原始 URI?

标签: android kotlin android-room android-jetpack-compose


【解决方案1】:

我将 uri 保存为 Room 数据库中的字符串

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

如果您将ActivityResultContracts.GetContent() 更改为ActivityResultContracts.OpenDocument(),并在ContentResolver 上调用takePersistableUriPermission() 以获得Uri,则您可以长期访问内容。

【讨论】:

    【解决方案2】:

    创建自己的 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
    }
    

    }

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 2017-03-18
    • 1970-01-01
    • 2014-07-27
    • 2013-02-11
    • 1970-01-01
    • 2021-03-29
    • 2020-08-01
    • 2021-01-09
    • 1970-01-01
    相关资源
    最近更新 更多