简体   繁体   English

为什么在 Compose 中使用喷气背包导航时视图会一直闪烁?

[英]Why the view keeps flashing when using jetpack navigation with Compose?

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).问题是,当显示新屏幕(又名Screen.AccountsScreen )时,其内容不断闪烁/重绘,并且永远不会被破坏的登录表单也会发生同样的事情(我知道这一点,因为日志消息“Recomponing...”得到印刷无止境)。 I assume this happens because the isLoginSuccessful state is always true.我认为这是因为isLoginSuccessful状态始终为真。 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 }
    }
}

You shouldn't change state directly from view builders.您不应直接从视图构建器更改状态。 In this case LaunchedEffect should be used:在这种情况下,应该使用LaunchedEffect

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

Check out more in side effects documentation .在副作用文档中查看更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 Compose Navigation 导航时 TopAppBar 闪烁 - TopAppBar flashing when navigating with Compose Navigation 使用 Jetpack Navigation 时 Compose Fragment 崩溃应用程序 - Compose Fragment crashes application when using Jetpack Navigation 如何使用手柄和负责导航的视图模型在 Jetpack Compose 上设置 android 导航? - How to setup android navigation on jetpack compose using hilt with view models responsible for navigation? Android Jetpack Compose 在导入导航撰写时崩溃 - Android Jetpack Compose crashes when importing navigation compose Android Jetpack 撰写和导航 - Android Jetpack Compose and Navigation Jetpack 使用 viewModel 组合导航 - Jetpack compose navigation with viewModel 使用 Jetpack Compose Navigation 时导航图是否已过时? - Is the navigation graph obsoleted when I use Jetpack Compose Navigation? 在 jetpack compose 中使用视图 model 的最佳实践 - Best practise of using view model in jetpack compose 从 jetpack 组合导航使用 popBackStack 时如何更改脚手架顶部栏的标题? - How to change title for scaffold top bar when using popBackStack from jetpack compose navigation? 使用伴奏导航时如何隐藏 Jetpack Compose 中的底部栏 Animation - How to hide bottom bar in Jetpack Compose when using Accompanists` Navigation Animation
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM