`val isFirstTime by vm.isFirstTime.collectAsStateW...
# compose
u
val isFirstTime by vm.isFirstTime.collectAsStateWithLifecycle()
NavHost(
navController = navController,
startDestination = if (isFirstTime) NavGraph.OnBoarding else NavGraph.Home,
Where is my mistake ? When opening the application, OnBoarding it is displayed for half a second then it goes to Home and it's really not pretty
m
Isfirsttime you store datastore retrieve 0.5 second so, home screen show after onboarding screen show Use run blocking in datastore isfirsttime retrieve
u
Wow it's work ! Thanks a lot 🙂
c
Wow, very bad idea to use run blocking 😅 You should introduce a better logic and show a splash screen or loading spinner. Return null as initial value - show the loading spinner and then return the start destination and use it as the value, no need for a Boolean.
1
s
You also should not have a conditional start destination in the first place, that should be consistent. https://developer.android.com/guide/navigation/use-graph/conditional

https://youtu.be/09qjn706ITA?si=9NFk6y60OBHSzO6f

at 4:55 starts taking about this too. You want something else to observe this information and navigate accordingly instead.
👍 1
u
Thanks evryone, I tried to listen to your advice, can you tell me if it is correct? I created a sealed class NavState
sealed class NavState {
object Loading: NavState()
object FirstTime: NavState()
object NotFirstTime: NavState()
}
and I created a composable that return the correct destination
@Composable
fun composeNavigationApp(
viewModel: NavViewModel
) : NavGraph {
val viewState by viewModel.navState.collectAsState()
return when(viewState) {
NavState.FirstTime -> NavGraph.OnBoarding
NavState.Loading -> NavGraph.Loading
NavState.NotFirstTime -> NavGraph.Home
}
}
I created a NavViewModel to manage the state
class NavViewModel(repository: PreferencesRepository) : ViewModel() {
val isFirstTime: Flow<Boolean> = repository.isFirstTime
val navState = isFirstTime.map { isFirstTime ->
if (isFirstTime) {
NavState.FirstTime
} else {
NavState.NotFirstTime
}
}.stateIn(viewModelScope, SharingStarted.Lazily, NavState.Loading)
}
And i use it like this in my NavHost
val navViewModel : NavViewModel = koinViewModel()
NavHost(
navController = navController,
startDestination = composeNavigationApp(viewModel = navViewModel),
s
No this is still changing your startDestination. You want that to be fixed. Otherwise when you deep link somewhere and then you call navigateUp for example, you won't have a reliable scenario of where you'd end up, but it'd depend on what this had resolved to.
u
Ah so I have to modify my composeNavigationApp function so that it returns a composable?
s
The start destination should be what you want the users to see last before they exit the app by pressing back. A login flow or an onboarding flow are conditional scenarios, not the default start destination. What we do is have the real destination as the start destination, and we have an effect above the NavHost observing the login state to conditionally take you out to the login flow, and when you're done with that you can go back to the real start destination. https://github.com/HedvigInsurance/android/blob/develop/app%2Fapp%2Fsrc%2Fmain%2Fkotlin%2Fcom%2Fhedvig%2Fandroid%2Fapp%2Fui%2FHedvigApp.kt#L175
No, your startDestination should really just be a fixed value pointing to your app's start destination which has no conditions like being logged out, not having done the onboarding yet etc.
u
I think I'm starting to understand (I'm a beginner, I think it shows 🙂 ), is it better?
@Composable
fun composeNavigationApp(
navController: NavController,
viewModel: NavViewModel
) {
val viewState by viewModel.navState.collectAsState()
LaunchedEffect(viewState) {
when (viewState) {
is NavState.FirstTime -> navController.navigate(NavGraph.OnBoarding)
is NavState.NotFirstTime -> navController.navigate(NavGraph.Home) {
popUpTo(NavGraph.OnBoarding) { inclusive = true }
}
}
}
}
Thank you so much anyway
and in my navhost
NavHost( navController = navController, startDestination = NavGraph.Home
s
Shouldn't the pop be on the other one? Since now if you're onboarding, you're not popping anything, so if you press back you'd drop the onboarding and go back to just home. Is this what you wanted? And you probably don't need to do anything to navigate to Home, you'll be at Home already anyway if you do nothing