android-jetpack-compose - Ui 未从 viewmodel kotlin flow 更新

标签 android-jetpack-compose android-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() }
        }
    }

View 模型:

@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
        }
    }
}

最佳答案

您的代码中有两个问题:

  • mainViewModel.mutableState.value 仅从可变状态获取当前值。当该值更改时,您的可组合项不会收到通知,因此它无法反射(reflect)更改。如果您想在 View 模型中使用 LiveData,则必须使用 observeAsState() extension function它将 LivaData 转换为可以通过可组合函数自动观察的 State。另一种选择是直接在 View 模型中使用 (Mutable)State 。请参阅this说明。
  • 每次 Grid() 函数重组时,都会调用您的 mainViewModel.getData() 函数,这将在每次 mainViewModel.mutableState 时调用code> 更改(一旦您正确观察)。你绝对不希望这样。更好的解决方案是从 viewModel 的 init block 中调用 getData() ,或者,如果您确实需要从可组合函数中调用它,请使用 LaunchedEffect .

顺便说一句,您创建流然后将其收集到 LiveData 中的方式确实很奇怪而且没有必要。你可以这样做:

fun getData() = viewModelScope.launch {
    mutableState.value = Resource.Loading
    try {
        val mResponse = dashBoardRepository.getDevice()
        mutableState.value = Resource.Success(mResponse)
    } catch (e: Exception) {
        e.printStackTrace()
        mutableState.value = Resource.Error("Error")
    }
}

关于android-jetpack-compose - Ui 未从 viewmodel kotlin flow 更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71379141/

相关文章:

android - Jetpack Compose wrapContentHeight/heightIn 在按钮周围添加了额外的空间

android - 修复了 Jetpack Compose 中 LazyColumn 内的网格?

android - ViewModel 中的实例成员 LiveData 变量?

android - SharedFlow 不从发射中收集

java - Kotlin Flows Java 互操作回调

android - 如何在 Android Jetpack Compose 中制作圆底导航

java - 为什么jetpack compose中没有热重载?理论上他们将来是否有可能在 compose 中添加类似热重载的 flutter 功能?

android - Dao类的实例未正确初始化

android - 如何在父 fragment 和子 fragment 内的 fragment 之间共享 ViewModel

android - debounce() Kotlin Flow 运算符不适用于每个新 Flow 创建,如何解决此问题?