mutableStateOf 在视图模型中更新,但在 @Compose 中没有效果

问题描述 投票:0回答:2

我的 HiltViewModel 中有一个 mutableStateof,名为“loading”。我正在更新从视图模型中的函数加载的值,该值被传递给 @composable 函数并在那里使用。 情况是加载值在 viewModel 中完美更新,但没有反映在 @Composable 函数中。 我的视图模型是:

@HiltViewModel
class AuthenticationViewModel @Inject constructor(
    private val repository: AppRepository,
    application: Application
): ViewModel() {
   val loading = mutableStateOf(false)

   fun update() = viewModelScope.launch {
      loading.value = true
   }
}

加载值在此处更新,但未反映在@composable中

@Composable
fun LoginScreen(
    viewModel: AuthenticationViewModel,
    actions: MainActions
) {
    val loading = viewModel.loading.value

    //Loading is another composable function where bool value is passed
    Loading(state = loading)
    CustomNavigationButton(title = "Sign In",enabled = true,onClick = 
    {viewModel.update()})
}

现在,当我单击导航按钮时,将调用视图模型函数,并且加载状态也会更新,但不会反映在 @Composable 中

加载可组合项是:

@Composable
fun Loading(state:Boolean) {
    var showDialog by remember { mutableStateOf(state) }

    if(showDialog){
        Dialog(onDismissRequest = { showDialog = false }, DialogProperties(
            dismissOnBackPress = false,dismissOnClickOutside = false
        )) {
            Box(
                modifier = Modifier.size(100.dp).background(Color.White, shape = RoundedCornerShape(8.dp)),
                contentAlignment= Alignment.Center,
            ){
                CircularProgressIndicator()
            }
        }
    }
}
android kotlin android-jetpack-compose android-jetpack
2个回答
4
投票

问题出在 Loader 可组合函数中。 if 条件始终设置为 false,因为可变状态在该特定可组合函数中永远不会更新。 替换:

@Composable
fun Loading(state:Boolean) {
    var showDialog by remember { mutableStateOf(state) }

    if(showDialog){
        Dialog(onDismissRequest = { showDialog = false }, DialogProperties(
            dismissOnBackPress = false,dismissOnClickOutside = false
        )) {
            Box(
                modifier = Modifier.size(100.dp).background(Color.White, shape = RoundedCornerShape(8.dp)),
                contentAlignment= Alignment.Center,
            ){
                CircularProgressIndicator()
            }
        }
    }
}

@Composable
fun Loading(state:Boolean) {
    if(state){
        Dialog(onDismissRequest = {}, DialogProperties(
            dismissOnBackPress = false,dismissOnClickOutside = false
        )) {
            Box(
                modifier = Modifier.size(100.dp).background(Color.White, shape = RoundedCornerShape(8.dp)),
                contentAlignment= Alignment.Center,
            ){
                CircularProgressIndicator()
            }
        }
    }
}

0
投票

要看到的是

state
并不是真正的状态;它只是一个值。您可以通过将其包裹在 mutableStateOf 中来
将其转变为状态
。对
state
(值)的任何更改都会触发
@Composable Loading
的重组,这正是您想要的。但是因为您告诉 Compose“记住”状态,所以它会说“好吧,有些东西触发了重新组合,这是我为您记住的
MutableState
。”

解决此问题的方法是告诉 Compose 何时忘记(即无效)并记住新内容。您可以通过在

key
上设置
remember
来做到这一点。如果您知道按键在副作用中的工作原理,那么这应该很熟悉:

var showDialog by remember(key1 = state) { mutableStateOf(state) }

当您这样做时,您不妨重构名称以使其更清晰:

@Composable
fun Loading(showDialog : Boolean) {
    var showDialogInternal by remember(key1 = showDialog) { mutableStateOf(showDialog) }
    ...
}

保留对记住的

showDialogInternal
的引用实际上只有帮助,因为您更新了
Loading
内的状态。如果没有,那么你根本不需要状态,你应该接受 @Ankit Shah 的答案,尽管目前还不清楚你如何实际关闭对话框

© www.soinside.com 2019 - 2024. All rights reserved.