Ui 未从 viewmodel kotlin flow 更新
我对 Android Flow 和 JetPack compose 很陌生,
我试图在更改可变状态时更新我的 UI,但这并没有调用我们的可组合项,这是我的代码
@Composable
fun Grid() {
val mainViewModel by viewModels<DashBoardViewModel>()
mainViewModel.getData()
when (val result = mainViewModel.mutableState.value) {
is Resource.Success -> {
LazyVerticalGrid(
cells = GridCells.Adaptive(100.dp)
) {
items(result.device.items.first().devices.count()) {
EachItem(it)
}
}
}
is Resource.Error -> { Text(text = result.message) }
Resource.Loading -> { CircularProgressIndicator() }
Resource.Empty -> {}
else -> { CircularProgressIndicator() }
}
}
ViewModel:
@HiltViewModel
class DashBoardViewModel @Inject constructor(
private val dashBoardRepository: DashBoardRepository
) : ViewModel() {
val mutableState = MutableLiveData<Resource>()
fun getData() = viewModelScope.launch {
flow {
emit(Resource.Loading)
try {
val mResponse = dashBoardRepository.getDevice()
emit(Resource.Success(mResponse))
} catch (e: Exception) {
e.printStackTrace()
emit(Resource.Error("Error"))
}
}.flowOn(Dispatchers.IO).collect {
mutableState.value = it
}
}
}
I am quite new in Android Flow and JetPack compose,
I am trying to update my UI when mutable state is being changed , but this is not calling our composable , here is my code
@Composable
fun Grid() {
val mainViewModel by viewModels<DashBoardViewModel>()
mainViewModel.getData()
when (val result = mainViewModel.mutableState.value) {
is Resource.Success -> {
LazyVerticalGrid(
cells = GridCells.Adaptive(100.dp)
) {
items(result.device.items.first().devices.count()) {
EachItem(it)
}
}
}
is Resource.Error -> { Text(text = result.message) }
Resource.Loading -> { CircularProgressIndicator() }
Resource.Empty -> {}
else -> { CircularProgressIndicator() }
}
}
ViewModel:
@HiltViewModel
class DashBoardViewModel @Inject constructor(
private val dashBoardRepository: DashBoardRepository
) : ViewModel() {
val mutableState = MutableLiveData<Resource>()
fun getData() = viewModelScope.launch {
flow {
emit(Resource.Loading)
try {
val mResponse = dashBoardRepository.getDevice()
emit(Resource.Success(mResponse))
} catch (e: Exception) {
e.printStackTrace()
emit(Resource.Error("Error"))
}
}.flowOn(Dispatchers.IO).collect {
mutableState.value = it
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的代码中有两个问题:
mainViewModel.mutableState.value
仅从可变状态获取当前值。当该值更改时,您的可组合项不会收到通知,因此它无法反映更改。如果您想在视图模型中使用LiveData
,则必须使用observeAsState()
扩展函数,将LivaData
转换为可自动观察的State
可组合的 功能。另一种选择是直接在视图模型中使用(Mutable)State
。请参阅此状态说明。Grid()
函数重组时,即每次mainViewModel.mutableState
更改时,都会调用您的mainViewModel.getData()
函数(一旦你正确观察)。你绝对不希望这样。更好的解决方案是从 viewModel 的init
块中调用getData()
,或者,如果您确实需要从可组合函数中调用它,请使用 LaunchedEffect。而且,作为旁注,您创建流然后将其收集到 LiveData 中的方式确实很奇怪而且没有必要。你可以这样做:
There are two problems in your code:
mainViewModel.mutableState.value
gets only the current value from your mutable state. Your composable will not be notified when this value changes and thus it cannot reflect the change. If you want to useLiveData
in your viewmodel, you have to useobserveAsState()
extension function which convertsLivaData
toState
that can be automatically observed by composable function. Other option is to have(Mutable)State
directly in your viewmodel. See this state explanation.mainViewModel.getData()
function will be called every time yourGrid()
function recomposes, which will be every time yourmainViewModel.mutableState
changes (once you observe it correctly). You definitely don't want that. Better solution would be to callgetData()
from your viewModel'sinit
block, or, if you really need to call it from your composable function, use LaunchedEffect.And, as a side note, the way you are creating flow and then collecting it into
LiveData
is really odd and unnecessary. You can do something like this instead: