Colton Idle
08/19/2022, 5:03 PMBox(modifier = Modifier.fillMaxSize()) {
Box(modifier = Modifier.align(Alignment.Center)) {
AppRouter(navController)
}
// This is my splash screen
AnimatedVisibility(
vm.appState.showSplashScreen,
enter = EnterTransition.None,
exit = fadeOut()) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center) { ArtificialSplashScreen() }
}
}
Inside of my app router, I do a check around most screens to see if the user is logged out. If so then I navigate to the login screen via a launchedEffect.
composable(Screen.Home.route) {
RequireSignedInUser(navController) {
HomeScreen()
}
}
@Composable
fun RequireSignedInUser(
navController: NavController,
content: @Composable () -> Unit
) {
val user by appState.currentUser.collectAsState()
if (user == null) {
LaunchedEffect(Unit) { navController.navigate(route = Screen.Login.route) }
This works 99.9% of the time but it seems like sometimes the launchedEffect isn't triggered (either that or the navigate call is failing somehow?). I can repro this... just supppppper infrequently but I do have users complaining. This only seems to happen on fresh installs (user not logged in) Any thoughts?Alex Vanyo
08/19/2022, 5:13 PMif (user != null)
is that condition expected? Navigate to the login if the user
is not null?Colton Idle
08/19/2022, 5:15 PMAlex Vanyo
08/19/2022, 5:22 PMcurrentUser
gets updated. What is the default value, and does it end up being null
in the case where the expected navigate doesn’t happen?
For a race condition like this, my instinct is that currentUser
is updated multiple times in short succession, and you can’t rely on any intermediate values being received and acted upon by the LaunchedEffect
Colton Idle
08/19/2022, 5:32 PMval currentUser: StateFlow<AppUser?>
One thing to add that I should've said already, is that the user check if it fails... it loads the content(). But the content never loads. It's just a blank screen. Hence why I think it does make it to the launchedEffect, but it just doesn't get called, or navigate doesn't get called?
if (user == null) {
LaunchedEffect(Unit) { navController.navigate(route = Screen.Login.route) }
} else {
content()
}
and you can’t rely on any intermediate values being received and acted upon by theThis statement definitely has me questioning my implementation. hm...LaunchedEffect
Alex Vanyo
08/19/2022, 6:25 PMcould force a LaunchEffect to be calledThe keys for your
LaunchedEffect
would be the way to restart the effect, if the keys change. So the current key of Unit
implies that it’d only call navigate
the first time the user
is null
and that composable is present.
So maybe some other place is calling navigate
right after this effect navigates to Login
? You might want to log all of your navigate calls, and see if the order and which ones are happening are what you’d expect.Colton Idle
08/19/2022, 7:02 PM.collectAsState(initial = null)
16:22:25.521 5362-5362/? E/ME: RequireSignedInUser recomposed
16:22:25.521 5362-5362/? E/ME: nav to sign up
16:22:25.581 5362-5362/? E/ME: RequireSignedInUser recomposed
16:22:25.581 5362-5362/? E/ME: nav to sign up
16:22:25.748 5362-5362/? E/ME: RequireSignedInUser recomposed
16:22:25.748 5362-5362/? E/ME: nav to sign up
16:22:25.910 5362-5362/? E/ME: RequireSignedInUser recomposed
16:22:25.910 5362-5362/? E/ME: nav to sign up
16:22:25.946 5362-5362/? E/ME: RequireSignedInUser recomposed
16:22:25.946 5362-5362/? E/ME: nav to sign up
16:22:26.276 5362-5362/? E/ME: RequireSignedInUser recomposed
16:22:26.276 5362-5362/? E/ME: nav to sign up
looks like it tried to nav 6 times in a second. getting closer...fun RequireSignedInUser(
with no luck. still doesn't' repro easily.jossiwolf
08/22/2022, 10:12 AMrook
08/22/2022, 4:07 PMLaunchedEffect
. navigate
is not a suspend and there’s no reason to delay the navigation until recomposition is completed.Colton Idle
08/23/2022, 4:50 AMrook
08/25/2022, 4:51 PMColton Idle
08/26/2022, 11:13 PM