将可组合值参数设置为挂起函数的结果
Set Composable value parameter to result of suspend function
我是 Compose 和 Kotlin 的新手。我有一个使用 Room 数据库的应用程序。在前端,有一个包含图标可组合项的可组合项。我希望根据在挂起函数中执行的数据库操作的结果来设置图标资源。
我的可组合项看起来像这样:
@Composable
fun MoviePreview(movie : ApiMoviePreview, viewModel: ApiMovieViewModel) {
Card(
modifier = ...
) {
Row(
modifier = ...
) {
IconButton(
onClick = {
//...
}) {
Icon(
imageVector =
// This code does not work, as isMovieOnWatchList() is a suspend function and cannot be called directly
if (viewModel.isMovieOnWatchlist(movie.id)) {
Icons.Outlined.BookmarkAdded
} else {
Icons.Filled.Add
}
,
contentDescription = stringResource(id = R.string.addToWatchlist)
)
}
}
}
}
我需要调用的函数是一个挂起函数,因为 Room 要求它的数据库操作发生在一个单独的线程上。函数 isMovieOnWatchlist()
如下所示:
suspend fun isMovieOnWatchlist(id: Long) {
return movieRepository.isMovieOnWatchlist(id)
}
实现所需行为的适当方法是什么?我已经偶然发现了协程,但问题是似乎没有办法 return 从协程函数中提取一个值。
更好的方法是准备数据,以便您需要的一切都在 data/value class 中,而不是按 row/item 执行实时查找,这不是很有效。我假设您有 2 tables 并且您可能想要一个 LEFT JOIN 但是所有这些细节都不包括在内。
对于 Room,它甚至包括使用 Flow
api 的实现,这意味着它将在 table 和 re-runs 原始查询中的信息发生变化时观察数据为您提供新的更改数据集。
然而,这超出了您最初问题的范围,但如果您想探索这个问题,那么这是一个好的开始:https://developer.android.com/codelabs/basic-android-kotlin-training-intro-room-flow#0
针对你原来的问题。这可能可以通过组合项中的 LaunchedEffect
和一些观察到的 MutableState<ImageVector?>
对象来实现,例如:
@Composable
fun MoviePreview(
movie: ApiMoviePreview,
viewModel: ApiMovieViewModel
) {
var icon by remember { mutableStateOf<ImageVector?>(value = null) } // null or default icon until update by result below
Card {
Row {
IconButton(onClick = {}) {
icon?.run {
Icon(
imageVector = this,
contentDescription = stringResource(id = R.string.addToWatchlist))
}
}
}
}
LaunchedEffect(Unit) {
// execute suspending function in provided scope closure and update icon state value once complete
icon = if (viewModel.isMovieOnWatchlist(movie.id)) {
Icons.Outlined.BookmarkAdded
} else Icons.Filled.Add
}
}
我是 Compose 和 Kotlin 的新手。我有一个使用 Room 数据库的应用程序。在前端,有一个包含图标可组合项的可组合项。我希望根据在挂起函数中执行的数据库操作的结果来设置图标资源。
我的可组合项看起来像这样:
@Composable
fun MoviePreview(movie : ApiMoviePreview, viewModel: ApiMovieViewModel) {
Card(
modifier = ...
) {
Row(
modifier = ...
) {
IconButton(
onClick = {
//...
}) {
Icon(
imageVector =
// This code does not work, as isMovieOnWatchList() is a suspend function and cannot be called directly
if (viewModel.isMovieOnWatchlist(movie.id)) {
Icons.Outlined.BookmarkAdded
} else {
Icons.Filled.Add
}
,
contentDescription = stringResource(id = R.string.addToWatchlist)
)
}
}
}
}
我需要调用的函数是一个挂起函数,因为 Room 要求它的数据库操作发生在一个单独的线程上。函数 isMovieOnWatchlist()
如下所示:
suspend fun isMovieOnWatchlist(id: Long) {
return movieRepository.isMovieOnWatchlist(id)
}
实现所需行为的适当方法是什么?我已经偶然发现了协程,但问题是似乎没有办法 return 从协程函数中提取一个值。
更好的方法是准备数据,以便您需要的一切都在 data/value class 中,而不是按 row/item 执行实时查找,这不是很有效。我假设您有 2 tables 并且您可能想要一个 LEFT JOIN 但是所有这些细节都不包括在内。
对于 Room,它甚至包括使用 Flow
api 的实现,这意味着它将在 table 和 re-runs 原始查询中的信息发生变化时观察数据为您提供新的更改数据集。
然而,这超出了您最初问题的范围,但如果您想探索这个问题,那么这是一个好的开始:https://developer.android.com/codelabs/basic-android-kotlin-training-intro-room-flow#0
针对你原来的问题。这可能可以通过组合项中的 LaunchedEffect
和一些观察到的 MutableState<ImageVector?>
对象来实现,例如:
@Composable
fun MoviePreview(
movie: ApiMoviePreview,
viewModel: ApiMovieViewModel
) {
var icon by remember { mutableStateOf<ImageVector?>(value = null) } // null or default icon until update by result below
Card {
Row {
IconButton(onClick = {}) {
icon?.run {
Icon(
imageVector = this,
contentDescription = stringResource(id = R.string.addToWatchlist))
}
}
}
}
LaunchedEffect(Unit) {
// execute suspending function in provided scope closure and update icon state value once complete
icon = if (viewModel.isMovieOnWatchlist(movie.id)) {
Icons.Outlined.BookmarkAdded
} else Icons.Filled.Add
}
}