我有一个使用 jetpack compose 构建的电影应用程序。我在其中展示了用户选择的最喜欢的电影。收藏夹应该完美地存在于用户界面中,但是当我从用户界面中删除项目时,用户界面不会立即重新组合以反映更改。该怎么办?
这是我的用户界面
@composable
fun favscreen(
movieviewmodel: movieviewmodel
) {
remember { mutablestateof(movieviewmodel.getfavmovies()) }
val shouldshowdialog = remember { mutablestateof(false) }
val uistates = movieviewmodel.favs.collectasstate()
column {
row {
text(
text = "fav movies",
fontsize = 25.sp,
fontfamily = fontfamily(font(r.font.nsb)),
modifier = modifier.padding(20.dp).weight(1f)
)
iconbutton(onclick = {
shouldshowdialog.value = true
}) {
icon(icons.filled.delete, contentdescription = "")
}
}
when(val currentstate = uistates.value){
is movieviewmodel.uistates.loading -> {
box(modifier = modifier.fillmaxsize(), contentalignment = alignment.center) {
circularprogressindicator()
}
}
is movieviewmodel.uistates.favs -> {
val data = currentstate.data
if(data.isempty()){
box(modifier = modifier.fillmaxsize(), contentalignment = alignment.center) {
text(
text = "no fav movies",
fontsize = 25.sp,
fontfamily = fontfamily(font(r.font.nsb)),
modifier = modifier.padding(20.dp))
}
}
else {
lazycolumn(){
items(data){ fav ->
row(modifier = modifier
.padding(20.dp)
.fillmaxwidth()
.clip(roundedcornershape(16.dp))
.background(color = color.darkgray)) {
asyncimage(
model = utils.image_url + fav.imageurl,
contentdescription = "",
contentscale = contentscale.crop,
filterquality = filterquality.high,
modifier = modifier
.width(150.dp)
.height(150.dp))
column(modifier = modifier.padding(20.dp)) {
text(
text = fav.title!!,
fontsize = 20.sp,
fontfamily = fontfamily(font(r.font.nsb)))
text(
text = fav.rating.tostring() + "/10 imdb",
fontsize = 15.sp,
fontfamily = fontfamily(font(r.font.nsb)))
text(
text = "movie id : #" + fav.movieid,
fontsize = 15.sp,
fontfamily = fontfamily(font(r.font.nsb)))
}
}
}
}
}
}
is movieviewmodel.uistates.error -> {
box(modifier = modifier.fillmaxsize(), contentalignment = alignment.center){
text(
text = "no fav movies",
fontsize = 25.sp,
fontfamily = fontfamily(font(r.font.nsb)),
modifier = modifier.padding(20.dp))
}
}
else -> {}
}
}
if (shouldshowdialog.value){
alertdialog(
ondismissrequest = { shouldshowdialog.value = false },
confirmbutton = {
textbutton(onclick = {
movieviewmodel.deletemovies()
shouldshowdialog.value = false
}) {
text(text = "proceed", fontfamily = fontfamily(font(r.font.nsm)))
}
},
dismissbutton = {
textbutton(onclick = {
shouldshowdialog.value = false
}) {
text(text = "cancel", fontfamily = fontfamily(font(r.font.nsm)))
}
},
shape = roundedcornershape(16.dp),
text = { text(text = "favs deletion",fontfamily = fontfamily(font(r.font.nsb)))},
title = { text(text = "do you want to delete all fav movies ?", fontfamily = fontfamily(font(r.font.nsb)))}
)
}
}这是我的视图模型
@HiltViewModel
class MovieViewModel @Inject constructor(
private val movieRepoImpl: MovieRepoImpl
) : ViewModel() {
private val _favs : MutableStateFlow<UiStates> = MutableStateFlow(UiStates.INITIAL)
val favs get() = _favs.asStateFlow()
// MOVIE DAO
fun getFavMovies() = viewModelScope.launch {
try {
_favs.value = UiStates.LOADING
movieRepoImpl.getFavs().collectLatest {
_favs.value = UiStates.FAVS(it)
}
} catch (ex : Exception){
_favs.value = UiStates.ERROR(ex.localizedMessage!!)
}
}
fun insertMovie(favModel: FavModel) = viewModelScope.launch {
movieRepoImpl.insertFav(favModel)
}
fun deleteMovies() = viewModelScope.launch {
movieRepoImpl.deleteAllMovies()
}
sealed class UiStates {
object LOADING : UiStates()
data class FAVS(val data : MutableList<FavModel>) : UiStates()
data class ERROR(val error : String) : UiStates()
object INITIAL : UiStates()
}
}当您查看 _favs 的写入用法时,问题变得非常明显:
只有 getfavmovies 会更新它。
虽然这听起来像“你应该在删除功能中更新你的用户界面状态”,但我想提出一个替代解决方案:
利用 room + flows 的力量!
首先在 viewmodel 中定义 loadingstate,它将存储为流:
sealed class loadingstate {
object loading : loadingstate()
data class success : loadingstate()
data class error(val error : string) : loadingstate()
object initial : loadingstate()
}
private val loadingstate = mutablestateflow<loadingstate>(initial)然后,更改 getfavmovies() 函数以使用此机制:
fun getfavmovies() {
viewmodelscope.launch {
try {
_loadingstate.value = loadingstate.loading
movierepoimpl.loadfavs() // a function which triggers e.g. a network call to actually load your movies
_loadingstate.value = loadingstate.success
} catch (ex: exception) {
_loadingstate.value = loadingstate.error(ex.localizedmessage!!)
}
}
}最后,结合你的状态和数据,让奇迹发生。一旦其中之一发生变化,这将自动更新:)
val favs: flow<uistates> = combine(
movierepoimpl.getmovies(),
loadingstate
) { movies, loadingstate ->
when (loadingstate) {
is loadingstate.loading -> uistates.loading
is loadingstate.success -> uistates.success(movies)
is loadingstate.error -> uistates.error(error)
is loadingstate. initial -> uistates.initial
}
}免责声明:其中可能有拼写错误,我没有方便的 ide
让我们通过改进代码来结束这个答案:
避免将 = 用于不返回任何内容的函数(getfavmovies、insertmovie、deletemovies)。否则,你会例如期望 getfavmovies 返回电影列表
remember { mutablestateof(movieviewmodel.getfavmovies()) } 并没有真正的 remember 任何东西,是吗?这太令人恼火了。我建议将其移至 viewmodel 中: init { movieviewmodel.getfavmovies() }
val uistates = movieviewmodel.favs.collectasstate():命名意味着这是多个 ui 状态,请使用单数; uistates 类本身也是如此。另外,如果这里直接使用“.value”,可以跳过这里的重新声明:when(val currentstate = uistates.value)
您的 uistate 包含 mutablelist<favmodel>。对 ui 状态使用可变值是一个坏主意,例如它可能会混淆您的 stateflow。一定要避免这种情况。只需使用普通的旧列表:) https://www.php.cn/link/ff685590317f1330efc73f396ac92cd7
使用 collectasstatewithlifecycle() 而不是 collectasstate()。请参阅https://medium.com/androiddevelopers/consuming-flows -安全地在jetpack-compose-cde014d0d5a3
您绝对不应该在 viewmodel 中访问 repoimpl:将存储库拆分为接口和实现的整个想法是隐藏实现
定义一个 screen-composable 是个好主意,它不需要 viewmodel,只需要数据,类似于 https://developer.android.com/jetpack/compose/state#state-hoisting:
.
@Composable
private fun FavScreen(
val viewModel: MovieViewModel,
) {
FawScreen(
uiState = viewModel.fav.collectAsStateWithLifecycle().value,
shouldShowDialog = viewModel.shouldShowDialog.collectAsStateWithLifecycle().value
)
}
@Composable
private fun FavScreen(
val uiState: UiStates,
val shouldShowDialog: Boolean
) {
// your current ui
}以上就是使用房间数据库删除 jetpack 中的所有项目后,UI 未重新组合的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号