【问题标题】:Why the view keeps flashing when using jetpack navigation with Compose?为什么在 Compose 中使用 jetpack 导航时视图一直闪烁?
【发布时间】:2022-01-03 14:33:20
【问题描述】:

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

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

【问题讨论】:

  • 嗨!我的回答解决了你的问题吗?如果是这样,请使用投票柜台下的复选标记接受它。否则,如果您有任何问题,请告诉我。
  • @Pylyp Dukhov 我的屏幕有时也会闪烁,我还没有找到原因。在我的情况下,导航操作发生在按钮点击的 lambda 内。 Afaik 在这种情况下,我不需要使用 Launched 效果,因为 lambda 不是合成的一部分,但是当它发生时,我的合成状态会丢失,并且屏幕会闪烁。不知道我错过了什么
  • @quealegriamasalegre 这很难说,请将您的代码缩减为minimal reproducible example 并发布另一个问题,因为它似乎与这个问题无关。
  • 问题是我无法始终如一地重现它。我将尝试创造条件使其始终如一地发生,然后发布问题

标签: android kotlin android-jetpack-compose android-jetpack-navigation


【解决方案1】:

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

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

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

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

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

查看更多副作用documentation

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    • 2022-11-29
    • 1970-01-01
    相关资源
    最近更新 更多