如何在Jetpack Compose中根据DataStore值切换屏幕时防止闪烁效果?

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

我利用 DataStore 值 isLanguageSelected 来确定是显示

HomeScreen()
可组合项还是
LanguageScreen()
。虽然该功能按预期工作,但我遇到了一个问题,即转换到
LanguageScreen()
时会出现闪烁效果。例如,如果 DataStore 中的 isLanguageSelected 为 true,则它会在显示
LanguageScreen()
之前短暂显示
HomeScreen()
可组合项,从而导致闪烁效果。这是相关代码:

@Composable
fun MyAppNavHost(
    navController: NavHostController = rememberNavController()
) {

    val dataStore = LocalContext.current.dataStore
    val userPreferencesRepository = UserPreferencesRepository(dataStore)
    val isLanguageSelected by userPreferencesRepository.isLanguageSelected.collectAsState(initial = false)
    
        NavHost(
            navController = navController,
            startDestination = if (!isLanguageSelected) LanguageScreen.route else HomeScreen.route
        ){
            composable(HomeScreen.route) {
                HomeScreen()
            }
            composable(LanguageScreen.route) {
                LanguageScreen()
            }
        }
}

我尝试了一种解决方案,首先检查数据存储是否已加载,但我对该方法不满意。我正在寻找更专业的替代方案。这是我尝试过的代码:

var isDataLoaded by remember { mutableStateOf(false) }

LaunchedEffect(dataStore) {
    delay(1000)  
    isDataLoaded = true
}

if (isDataLoaded)
    NavHost(){} 
android-jetpack-compose android-jetpack android-jetpack-datastore navcontroller
1个回答
0
投票

我认为您观察到的闪烁是由这一行引起的:

collectAsState(initial = false)

这将使 Flow 最初返回 false,从而导致显示

LanguageScreen
。然后,从 DataStore 中读出实际值。整个 NavHost 将重新组合,新的
startDestination
设置为
HomeScreen

如果您只想在启动应用程序时从数据存储中读取单个值,我不确定您是否真的需要流程。

解决此问题的一种典型方法是添加加载屏幕可组合项。将加载可组合项设置为

startDestination
。然后,在该可组合项中,检查是否已选择语言。

@Composable
LoadingScreen(
    onLanguageSet: () -> Unit,
    onLanguageNotSet: () -> Unit
) {

    LaunchedEffect(Unit) {
        // read value from the datastore ...
        if (languageSelected) {
            onLanguageSet()
        } else {
            onLanguageNotSet()
        }
    }

    Box(
        contentAlignment = Alignment.Center,
        modifier = Modifier.fillMaxSize()
    ) {
        CircularProgressIndicator()
    }
}

然后,在您的 NavHost 中,将此可组合项添加为新目的地:

NavHost(
    navController = navController,
    startDestination = LoadingScreen.route
) {
    composable(LoadingScreen.route) {
        LoadingScreen(
            onLanguageSet = {
                navController.navigate(HomeScreen.route) {
                    popUpTo(LoadingScreen.route) {
                        inclusive = true  // prevent going back to loading screen when pressing back
                    }
                }
            }, 
            onLanguageNotSet = {
                navController.navigate(LanguageScreen.route) {
                    popUpTo(LoadingScreen.route) {
                        inclusive = true  // prevent going back to loading screen when pressing back
                    }
                }
            }
        )
    }
    composable(HomeScreen.route) {
        HomeScreen()
    }
    composable(LanguageScreen.route) {
        LanguageScreen()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.