ViewModel - 跳过开始屏幕 Jetpack Compose

问题描述 投票:0回答:1

我有一个开始屏幕(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:仅在第一次启动应用程序时显示开始屏幕的最佳方式

mvvm android-jetpack-compose
1个回答
0
投票

就我而言,我使用数据存储而不是共享首选项来获取数据作为流并在 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 中的用例

© www.soinside.com 2019 - 2024. All rights reserved.