【发布时间】:2023-02-18 06:49:49
【问题描述】:
我的想法是在那里呈现个人资料图片并允许用户更改它。
为了保存所选图片,我使用了SharedPreferences(将 Uri 保存为字符串)。问题是每次启动时图像都不会显示。
共享管理器检索到的值似乎是正确的,但 SubComposeAsyncImageContent 没有正确显示图片。
个人资料图片可组合:
@Composable
fun ProfilePicture(
imageUri: String?,
size: Dp = 50.dp,
onClick: (String) -> Unit,
) {
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.GetContent()) { uri: Uri? ->
onClick(uri.toString())
}
if (imageUri != null) {
Log.e("ProfilePicture", imageUri)
}
SubcomposeAsyncImage(
model = imageUri,
contentDescription = "",
modifier = Modifier.clickable { launcher.launch("image/*") }
) {
val state = painter.state
Log.e("ProfilePicState", "${state}")
if (state is AsyncImagePainter.State.Loading || state is AsyncImagePainter.State.Error) {
CircularProgressIndicator()
} else {
SubcomposeAsyncImageContent()
}
}
}
这个想法是 imageUri 作为参数从配置文件屏幕(包含 ProfilePicture)传递。配置文件屏幕从 viewModel 获取此值,它可以访问 sharedPreferences。
ProfileScreen.kt:
@Composable
fun ProfileScreen(viewModel: ProfileViewModel) {
var profileUri by rememberSaveable {
mutableStateOf(viewModel.getProfilePicURI())
}
Log.w("ProfileScreen", profileUri)
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
ProfilePicture(
imageUri = profileUri,
size = 150.dp,
onClick = {
viewModel.onEvent(ProfileEvents.OnUpdateProfilePic(it))
profileUri = viewModel.getProfilePicURI()
}
)
}
}
最后,viewModel:
class ProfileViewModel(val preferenceManager: PreferenceManager): ViewModel() {
fun getProfilePicURI(): String {
return preferenceManager.getProfilePic()
}
fun onEvent(event: ProfileEvents) {
when (event) {
is ProfileEvents.OnUpdateProfilePic -> {
// update the sharedpreference
preferenceManager.setProfilePic(event.newUri)
Log.e("ProfileVM", "uri stored: ${getProfilePicURI()}")
}
}
}
}
如前所述,代码在应用程序中工作,即我可以更改个人资料图片,即使我返回个人资料屏幕也会记住它,但在每次启动时,即使正确的资源似乎是,画家也无法加载图像发送。
日志如下所示:
2022-04-27 09:29:45.174 12502-12502/com.example.insurance W/ProfileScreen: content://com.android.providers.media.documents/document/image%3A96
2022-04-27 09:29:45.182 12502-12502/com.example.insurance E/ProfilePicture: content://com.android.providers.media.documents/document/image%3A96
2022-04-27 09:29:45.258 12502-12502/com.example.insurance E/ProfilePicState: Loading(painter=null)
2022-04-27 09:29:45.274 12502-12502/com.example.insurance E/ProfilePicState: Loading(painter=null)
2022-04-27 09:29:45.278 12502-12502/com.example.insurance E/ProfilePicState: Error(painter=null, result=coil.request.ErrorResult@bfc77785)
使用后退按钮退出应用程序有效,在重新创建时,个人资料图片就在那里。通过任务任务管理器销毁它会触发错误的行为。
当我启动应用程序时,显示个人资料图片的唯一方法是选择不同的图像,即如果我选择之前选择的 img,它不会显示。一旦我选择一个新的,它就会再次显示
【问题讨论】:
-
你不应该依赖这个 URI 在应用重启后可用,将文件本身复制到应用存储中并存储这个 URI
-
感谢您的回复,文件本身已经在设备存储中,因为它是从图库中获取的。此外,我认为这种情况正是我们拥有 URI 的原因。最后,我认为这与我的问题没有直接关系,因为文件“存在”但未显示,如果这有意义的话:D
-
它在那里,但您没有访问它的权限。 Android 只有在用户选择它后才会为您提供访问权限,并且会持续很短的时间 - 直到您的应用程序终止。当您选择上次启动时选择的相同图像时,不会触发重组,因为 URI 相同。如果你将它设置为
null,等待下一次用delay重组并用相同的值更新,你会看到它。 -
我明白了,现在更有意义了。为了获取文件并复制它,我正在尝试以下操作: val file = File(uri.path) val fl = File("Pictures/Insurance/profilePic.jpg") file.copyTo(fl, overwrite = true) Nontheless我得到一个空指针异常。它说该文件不存在,即使我只是从内部存储中选择它并在应用程序中显示它......你知道可能出了什么问题吗?
标签: android kotlin android-jetpack-compose