我正在制作一个练习应用程序,用于加载商店的库存。在屏幕内,我按下一个浮动按钮,生成一个对话框,询问用户从他们的图库中选择的多个数据中的图像。稍后,在对话框中按下保存按钮时,图像和其余数据将保存在ViewModel和ROOM中,然后在主屏幕上生成一个项目,同时显示这些数据,并使用Log.d打印。
在保存后生成项目时,它会正确显示,但是,如果我重新启动应用程序,则图像会消失。在生成图像和重新启动应用程序时,Log.d打印在两种情况下都显示相同的URI。
我的主要目标是在ROOM中保存图像、其地址或URI,然后加载带有图像的项目。我的研究表明,将URI保存为字符串是正确的做法,但我不知道保存图像的正确做法,如果必要,我也可以接受其他解决方案。
首先,在创建项目的对话框中,我像这样从图库中选择图像,并将其保存在ViewModel中,稍后保存到ROOM中:
val singlePhotoPickerLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.PickVisualMedia(),
onResult = { uri ->
selectedImageUri = uri
Log.d("URI RESULT", "$uri")
viewModel.onDialogChanged(
uri.toString()
)
}
)
当我按下“保存”按钮时,我将其保存在ROOM中:
DialogButton(
ButtonDefaults.buttonColors(
backgroundColor = verdeBillete,
contentColor = Color.White
), "Guardar", modifier = Modifier, onClick = {
viewModel.viewModelScope.launch {
viewModel.onAddSelected(
inventoryItem(
0,
uri,
)
)
}
onDismiss()
})
//add to ViewModel
fun onAddSelected(addItem: inventoryItem) {
viewModelScope.launch {
addItem(addItem)
getInventory()
}
}
//ROOM Table
@Entity(tableName = "inventory")
data class inventoryItem(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "r_id")
var id: Int = 0,
@ColumnInfo(name = "r_uri")
val uri: String,
)
然后我目前尝试像这样加载图像:
Log.d("Loading items", item.uri)
AsyncImage(
model = Uri.parse(item.uri),
contentDescription = null,
modifier = Modifier.fillMaxWidth(),
contentScale = ContentScale.Crop
)
从图库中选择图片后,该图片是可见的,但是在重新启动应用程序后,该图片会消失。在这两种情况下,Log.d 中打印的 URI 是相同的。
此外,我已经获得了以下权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
更新:在阅读了CommonsWare和Gowtham K K的两个答案并尝试实现它们后,我无法自己编写代码,因此我将帖子的内容(问题和两个答案)输入chatgpt并要求解决方案,它为我提供了以下解决方案,对我有用。
要使用takePersistableUriPermission,您必须执行以下操作:
首先,您需要具有读取或写入要持久保存的URI的权限。您可以通过在AndroidManifest.xml文件中添加以下代码行来实现:
或
然后,您需要获取要持久保存的URI。例如,如果您想保存从库中选择的图像的URI,则可以使用ActivityResultContracts.PickVisualMedia方法,如下所示:
val singlePhotoPickerLauncher =
rememberLauncherForActivityResult( contract =
ActivityResultContracts.PickVisualMedia(), onResult = { uri ->
selectedImageUri = uri } )
一旦你有了URI,你可以使用takePersistableUriPermission来持久保存它。takePersistableUriPermission方法应该在ContentResolver上使用,并带有两个参数:URI和访问模式(读或写)。例如:
contentResolver.takePersistableUriPermission(uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION) or
contentResolver.takePersistableUriPermission(uri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
最后,您可以将URI保存在ROOM数据库中作为文本字符串,并在需要时在应用程序中加载它。例如:
val inventoryItem = inventoryItem(0, uri.toString())
viewModel.onAddSelected(inventoryItem)
将所有东西组合在一起:
var selectedImageUri by remember {
mutableStateOf<Uri?>(null)
}
val singlePhotoPickerLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.PickVisualMedia(),
onResult = { uri ->
selectedImageUri = uri
Log.d("URI RESULT", "$uri")
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION//or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
val resolver = mContext.contentResolver
resolver.takePersistableUriPermission(uri!!, flags)
viewModel.onDialogChanged( //**save to database function**
uri.toString()
)
}
)