为什么在 Compose 中使用喷气背包导航时视图会一直闪烁? [英] Why the view keeps flashing when using jetpack navigation with Compose?

查看:38
本文介绍了为什么在 Compose 中使用喷气背包导航时视图会一直闪烁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个登录屏幕,当登录成功并且视图模型更新可变状态变量时,我的期望是调用一个新的可组合函数来显示新屏幕并删除登录屏幕.问题是,当显示新屏幕(又名 Screen.AccountsScreen)时,其内容不断闪烁/重绘,登录表单也发生同样的事情,它永远不会被破坏(我知道这是因为日志消息'Recomponing...' 被无限打印).我认为这是因为 isLoginSuccessful 状态始终为真.看来我需要一个只能消费一次的事件,对吗?如果是这样,我该怎么做?

I have a login scren and when the login is successful and the view model updates the mutable state variable, my expectation is that a new composable function is called to show a new screen and the login one is removed. The problem is that when the new screen (aka Screen.AccountsScreen) is shown, its content keeps flashing/redrawing and same thing happen with the login form which never gets destroyed (I know this because the log message 'Recomponing...' gets printed endless). I assume this happens because the isLoginSuccessful state is always true. It seems I need an event that can be consumed only once, is this correct? If so, how can I do that?

LoginViewModel.kt

@HiltViewModel
class LoginViewModel @Inject constructor() : ViewModel() {

  var isLoginSuccessful by mutableStateOf(false)
  var errorMessage by mutableStateOf("")
  
  fun onLoginClick(email: String, password:String) {
    errorMessage = ""
    if (credentialsValid(email, password)) {
      isLoginSuccessful = true
    } else {
      errorMessage = "Email or password invalid"
      isLoginSuccessful = false
    }
  }
}

LoginScreen.kt

@Composable
fun loginScreen(
  navController: NavController,
  viewModel: LoginViewModel = hiltViewModel()
) {
  println("Recomponing...")
  // Here gos the code for the login form
  
  if (viewModel.isLoginSuccessful) {
    navController.navigate(Screen.AccountsScreen.route) {
      popUpTo(Screen.LoginScreen.route) { inclusive = true }
    }
  }
}

推荐答案

复合导航在过渡期间重新组合消失和出现的视图.这是预期的行为.

Composite navigation recomposes both disappearing and appearing views during transition. This is the expected behavior.

您在每次重新组合时都调用了导航.您的问题在于以下几行:

You're calling navigate on each recomposition. Your problem lays in these lines:

if (viewModel.isLoginSuccessful) {
    navController.navigate(Screen.AccountsScreen.route) {
        popUpTo(Screen.LoginScreen.route) { inclusive = true }
    }
}

您不应直接从视图构建器更改状态.在这种情况下 LaunchedEffect 应该使用:

You shouldn't change state directly from view builders. In this case LaunchedEffect should be used:

LaunchedEffect(viewModel.isLoginSuccessful) {
    if (viewModel.isLoginSuccessful) {
        navController.navigate(Screen.AccountsScreen.route) {
            popUpTo(Screen.LoginScreen.route) { inclusive = true }
        }
    }
}

在副作用文档中查看更多信息.

Check out more in side effects documentation.

这篇关于为什么在 Compose 中使用喷气背包导航时视图会一直闪烁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆