首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在改变状态后,我的观点会多次重组自己。

在改变状态后,我的观点会多次重组自己。
EN

Stack Overflow用户
提问于 2021-09-05 09:42:35
回答 1查看 824关注 0票数 2

我正在做写作项目。我有一个简单的登录页面。单击“登录”按钮后,将在视图模型中设置loginState。问题是,当我在服务调用之后设置loginState时,我的可组合自我重新组合了多次。因此,导航控制器进行多次导航。我不明白这个问题。谢谢你的帮助。

我的可合成:

代码语言:javascript
运行
复制
@Composable
fun LoginScreen(
    navController: NavController,
    viewModel: LoginViewModel = hiltViewModel()
) {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.SpaceEvenly
    ) {
        val email by viewModel.email
        val password by viewModel.password
        val enabled by viewModel.enabled

        if (viewModel.loginState.value) {
            navController.navigate(Screen.HomeScreen.route) {
              popUpTo(Screen.LoginScreen.route) {
                 inclusive = true
              }
            }
        }

        LoginHeader()
        LoginForm(
            email = email,
            password = password,
            onEmailChange = { viewModel.onEmailChange(it) },
            onPasswordChange = { viewModel.onPasswordChange(it) }
        )
        LoginFooter(
            enabled,
            onLoginClick = {
                viewModel.login()
            },
            onRegisterClick = {
                navController.navigate(Screen.RegisterScreen.route)
            }
        )
    }

ViewModel类:

代码语言:javascript
运行
复制
@HiltViewModel
class LoginViewModel @Inject constructor(
    private val loginRepository: LoginRepository,
) : BaseViewModel() {

    val email = mutableStateOf(EMPTY)
    val password = mutableStateOf(EMPTY)
    val enabled = mutableStateOf(false)
    val loginState = mutableStateOf(false)

    fun onEmailChange(email: String) {
        this.email.value = email
        checkIfInputsValid()
    }

    fun onPasswordChange(password: String) {
        this.password.value = password
        checkIfInputsValid()
    }

    private fun checkIfInputsValid() {
        enabled.value =
            Validator.isEmailValid(email.value) && Validator.isPasswordValid(password.value)
    }

    fun login() = viewModelScope.launch {
        val response = loginRepository.login(LoginRequest(email.value, password.value))
        loginRepository.saveSession(response)
        loginState.value = response.success ?: false
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-05 10:55:45

您不应该从可组合构建器中直接造成副作用或更改状态,因为这将在每次重新组合时执行。

相反,您可以使用副作用。在您的例子中,可以使用LaunchedEffect

代码语言:javascript
运行
复制
if (viewModel.loginState.value) {
    LaunchedEffect(Unit) {
        navController.navigate(Screen.HomeScreen.route) {
            popUpTo(Screen.LoginScreen.route) {
                inclusive = true
            }
        }
    }
}

但是我认为更好的解决方案不是侦听loginState的更改,而是让login成为一个挂起函数,等待它完成,然后执行导航。您可以获得一个协同作用域,它将绑定到可以用rememberCoroutineScope组合的范围。它可以是这样的:

代码语言:javascript
运行
复制
suspend fun login() : Boolean {
    val response = loginRepository.login(LoginRequest(email.value, password.value))
    loginRepository.saveSession(response)
    return response.success ?: false
}

还请查看Google关于为什么不应该将NavController作为这个答案中的参数传递的想法(根据导航组成测试指南)

因此,更新后的视图如下:

代码语言:javascript
运行
复制
@Composable
fun LoginScreen(
    viewModel: LoginViewModel = hiltViewModel(),
    onLoggedIn: () -> Unit,
    onRegister: () -> Unit,
) {
    // ...
    val scope = rememberCoroutineScope()
    LoginFooter(
        enabled,
        onLoginClick = {
            scope.launch {
                if (viewModel.login()) {
                    onLoggedIn()
                }
            }
        },
        onRegisterClick = onRegister
    )
    // ...
}

以及你的航行路线:

代码语言:javascript
运行
复制
composable(route = "login") {
    LoginScreen(
        onLoggedIn = {
            navController.navigate(Screen.HomeScreen.route) {
                popUpTo(Screen.LoginScreen.route) {
                    inclusive = true
                }
            }
        },
        onRegister = {
            navController.navigate(Screen.RegisterScreen.route)
        }
    )
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69062221

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档