我有一个开始屏幕(onBoard)和一个身份验证视图模型,我希望在重新启动时跳过屏幕。我如何通过 ViewModel 执行此操作?
fun NavGraphBuilder.authNavGraph(navController: NavHostController){
navigation(
route = Graph.AUTHENTICATION,
startDestination = Screen.OnBoard.route
){
composable(route = Screen.OnBoard.route){
OnBoardScreen(navController = navController )
}
composable(route = Screen.SignUp.route){
SignUpScreen(navController = navController)
}
composable(route = Screen.CodeInput.route){
CodeInputScreen(navController = navController)
}
composable(route = Screen.AddPassword.route){
AddPasswordScreen(navController = navController)
}
composable(route = Screen.Register.route){
RegisterScreen(navController = navController)
}
}
}
@Composable
fun RootNavigationGraph(navController: NavHostController){
NavHost(
navController = navController,
route = Graph.ROOT,
startDestination = Graph.SPLASH, // There's just a switch to Graph.AUTH
enterTransition = {
EnterTransition.None
},
exitTransition = {
ExitTransition.None
}
){
composable(route = Graph.SPLASH){
SplashScreen(navController = navController)
}
authNavGraph(navController)
composable(route = Graph.TESTS){
MainScreen()
}
}
}
我还有带有 auth 和 main 的 NavGraph。同样,在身份验证启动屏幕后过渡到主屏幕。我做不到,我也不明白。我一直在寻找信息,要么我找得不好,要么我没有。预先感谢您的帮助!
我尝试通过共享首选项来做到这一点,但没有成功。
data class ScreensUIState(
var welcomeScreenSkipped: Boolean = false
)
class AuthViewModel(context: Context) : ViewModel() {
private val TAG = AuthViewModel::class.simpleName
var registrationUIState = mutableStateOf(RegistrationUIState())
var screensUIState = mutableStateOf(ScreensUIState())
private val sharedPreferences: SharedPreferences = context.getSharedPreferences("MyPrefs", Context.MODE_PRIVATE)
private fun setFirstLaunch() {
screensUIState.value = screensUIState.value.copy(
welcomeScreenSkipped = sharedPreferences.getBoolean("IsFirstLaunch", true)
)
}
fun onEvent(event: UIEvent){
when(event){
is UIEvent.WelcomeScreenSkipped -> {
setFirstLaunch()
}
这个答案不适合我: Jetpack Compose:仅在第一次启动应用程序时显示开始屏幕的最佳方式
就我而言,我使用数据存储而不是共享首选项来获取数据作为流并在 homeViewModel 上,您可以使用以下逻辑:
val startDestination = MutableStateFlow(Screen.Loading.route)
private suspend fun getStartDestination() {
dataStoreUtils.getIsFirstTime().collectLatest{ isFirstTime ->
startDestination.value =
if (isFirstTime) Screen.OnBoarding.route
else Screen.AuthScreen.route
}
}
}
init {
viewModelScope.launch {
getStartDestination()
}
}
对于数据存储使用此类:
class DataStoreUtils(
private val context: Context
) {
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_details")
suspend fun saveUsersFirstTime(isFirstTime: Boolean) {
context.dataStore.edit { preferences ->
preferences[IS_FIRST_TIME] = isFirstTime
}
}
fun getIsFirstTime(): Flow<Boolean> {
return context.dataStore.data.map { preferences ->
preferences[IS_FIRST_TIME] ?: true
}
companion object {
private val IS_FIRST_TIME = booleanPreferencesKey("is_first_time")
private val IS_DETAILS_FILLED =
booleanPreferencesKey("is_details_filled")
}
}
这里有趣的 getFirstTime() 从数据存储中读取并更新 startDestination,同时使用加载屏幕,同时更新此逻辑,以便不会出现任何其他不需要的屏幕。
如果您对这种方法还有任何疑问,请告诉我,因为它非常适合我在 Jetpack Compose 中的用例