我利用 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(){}
我认为您观察到的闪烁是由这一行引起的:
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()
}
}