I have an app with HorizontalPager
at startDestination screen and after I go to the last page, the app shows the home page.
When I open the app for second time it should show Home page immediately and never again show that startDestination screen with HorizontalPager
.
I used dataStore and it works, but the problem is that every time I open the app it flashes for a second that HorizontalPager
landing page and then it switches to the home page.
I used flow to get true/false state of the app start, so it will know it will know app was already opened for first time.
class MainActivity : ComponentActivity() {
@ExperimentalAnimationApi
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
WebSafeTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
val navController = rememberNavController()
Navigation(navController)
}
}
}
}
}
@ExperimentalAnimationApi
@ExperimentalMaterialApi
@ExperimentalFoundationApi
@ExperimentalPagerApi
@Composable
fun Navigation(
navController: NavHostController
) {
val context = LocalContext.current
val preferencesManager = PreferencesManager(context)
val preferencesFlow = preferencesManager.preferencesFlow
val scope = rememberCoroutineScope()
val result = remember { mutableStateOf(Constants.SKIP_LANDING_PAGE) }
scope.launch {
result.value = preferencesFlow.first().skipLandingPage
}
NavHost(
navController = navController,
//it goes it this line 2 times, first time when the app opens and second time after the flow is finished
startDestination = if (result.value) Screen.HomeScreen.route else Screen.LandingScreen.route,
modifier = Modifier.fillMaxSize()
) {
composable(
route = Screen.LandingScreen.route
) {
Landing(navController)
}
composable(
route = Screen.SkipChooseCountryScreen.route
) {
ChooseCountry()
}
composable(
route = Screen.HomeScreen.route
) {
Home(navController)
}
}
}
It goes to NavHost for the first time after app openes and it always returns FALSE as it is default value, after that flow returns TRUE(so it knows app was opened at least once before) and then it openes the correct screen.
I have no idea how to make NavHost to wait that flow to finishes. I tried to put NavHost into the scope but it didn't allow me.
CodePudding user response:
I also need to read data from data store, so this is how I do it:
Crossfade(
targetState = state.value.loadState
) { loadState ->
when (loadState) {
LoadState.NOT_LOADED -> Box(modifier = Modifier.fillMaxSize())
LoadState.SHOW_PIN -> PinScreen(
loadState = loadState,
state = state,
modifier = Modifier.fillMaxSize(),
)
LoadState.SHOW_CONTENT -> MainContent(
state = state,
)
}
}
Initially my state is NOT_LOADED
so I just display an empty box that fills the screen. You could alternatively display a spinner, or your app's logo. Once the data has been loaded, I show the PIN screen if the user has PIN enabled, or the main screen otherwise.
Also, note that you should not have your viewpager screen as your root destination, your home page should be your root destination, and you should conditionally navigate to the viewpager if the user has not seen your onboarding flow yet. Check this for details.