1

I cannot collect any state from the same Jetpack Compose screen(JCScreen), after having it wrapped in a NavHost.

The original working solution:
this JcScreen is for user sign in
the activity ActAuth

@AndroidEntryPoint
class ActAuth : AppCompatActivity() {
    private val viewModel: ViewModelAuth by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            ThemeBasicHRLQ {
                ScreenSignInWithInputValidationDebounce()
            }
        }

        // to collect the state `stateSignIn`,
        // and it works fine
        lifecycleScope.launch {
            lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.stateAuth.collect { state ->
                    ...
                }
            }
        }
    }
}

the digest of the JCScreen ScreenSignInWithInputValidationDebounce():

@OptIn(ExperimentalComposeUiApi::class, kInternalCoroutinesApi::class)
@Composable
fun ScreenSignInWithInputValidationDebounce(
    viewModel: ViewModelAuth = hiltViewModel()
){
    ....
    val stateSignIn by viewModel.stateAuth.collectAsState()
    ...
}

Everything works fine until I consolidating highly similar JCScreen for user sign up.

@AndroidEntryPoint
class ActAuth : AppCompatActivity() {
    private val viewModel: ViewModelAuth by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            ThemeBasicHRLQ {
                // the new JCScreen
                ScreenAuth()
            }
        }

        // to collect the state `stateSignIn`
        // but, with the new JCScreen, it does not work any more
        lifecycleScope.launch {
            lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.stateAuth.collect { state ->
                    ...
                }
            }
        }
    }
}
@Composable
fun ScreenAuth() {
    val navController = rememberNavController()
    NavHostAuth(navController = navController)
}
@Composable
fun NavHostAuth(
    navController: NavHostController,
) {
    NavHost(
        navController = navController,
        startDestination = NavRoutesAuth.SignIn.route
    ) {
        // I am still in this same JCScreen,
        // without using the `navController`
        composable(NavRoutesAuth.SignIn.route) {
            ScreenSignInWithInputValidationDebounce(navController)
        }

        composable(NavRoutesAuth.SignUp.route) {
            ScreenSignUpWithInputValidationDebounce(navController)
        }
        
    }
}

enum class NavRoutesAuth(val route: String) {
    SignIn("auth/signin"),
    SignUp("auth/signup"),
}

It looks to me that once wrapped into a NavHost, the state management is different.
Here may be a similar problem, with which, however, I still cannot solve my problem above.

Leon
  • 811
  • 10
  • 21
  • 1
    Does this answer your question? [Why is ViewModel initialized?](https://stackoverflow.com/questions/69002018/why-is-viewmodel-initialized) – Phil Dukhov Sep 06 '21 at 07:04
  • Philip, thanks. I have upvoted your answer and that question. With your answer, I feel much clearer, and will continue to work on the solution to this problem :). – Leon Sep 06 '21 at 07:12

0 Answers0