Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Navigation is being called every time in Jetpack Compose

I’m implementing registration in my application and, after filling in the respective fields, I click on a button that will make a registration request to the API. Meanwhile, I place a Loading View and when I receive the successful response, I execute the navigation to the OnBoarding screen. The issue is that the navController is always running the navigation and doing the navigation and popUp several times, when it should only do it once. I always get this warning on logs: Ignoring popBackStack to destination 29021787 as it was not found on the current back stack and I am not able to do any click or focus in the OnBoardingScreen.

My code:

val uiState by registerViewModel.uiState.collectAsState()

when (uiState) {
        is BaseViewState.Data -> {
            navController.navigate(NavigationItem.OnBoarding.route) {
                popUpTo(NavigationItem.Register.route) {
                    inclusive = true
                }
            }
        }
        is BaseViewState.Loading -> LoadingView()
        is BaseViewState.Error -> BannerView()
        else -> {}
    }

On button click I call the viewModel like this:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

registerViewModel.onTriggerEvent(
                    RegisterEvent.CreateUser(
                        usernameInputState.value.text,
                        emailInputState.value.text,
                        passwordInputState.value.text
                    )
                )

And, in ViewModel, I do my request like this:

override fun onTriggerEvent(eventType: RegisterEvent) {
        when (eventType) {
            is RegisterEvent.CreateUser -> createUser(eventType.username, eventType.email, eventType.password)
        }
    }

    private fun createUser(username: String, email: String, password: String) = safeLaunch {
        setState(BaseViewState.Loading)
        execute(createUser(CreateUser.Params(username, email, password))) {
            setState(BaseViewState.Data(RegisterViewState(it)))
        }
    }

I guess it should be caused by recomposition, because I put a breakpoint on first when scenario and it stops here multiple times, but only one on ViewModel. How can I fix this?

>Solution :

I can’t run on your code, but it looks similar to this and this.

This is the culprit.

is BaseViewState.Data -> {
        navController.navigate(NavigationItem.OnBoarding.route) {
            popUpTo(NavigationItem.Register.route) {
                 inclusive = true
            }
        }
}

Every time you call navController.navigate it will keep on passing through this block, executing an endless loop.

I suggest having the navigate call from a LaunchedEffect with a key

LaunchedEffect(key1 = "some key") {
     navController.navigate(…)
}

or creating a separate structure namely "Events" where they are emitted as SharedFlow and observed via a Unit keyed LaunchedEffect

LaunchedEffect(Unit) {
        viewModel.event.collectLatest {
            when (it) {
                is UiEvent.Navigate -> {
                    navController.navigate(…)
                }
            }
        }
    }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading