Jetpack Compose使用Navigation时启动后出现空白屏问题求助
问题:Compose导航导致闪屏后出现空白屏
我在Composable间实现简单导航时,遇到MainActivity启动性能问题。使用SplashScreen API实现闪屏,代码如下:
installSplashScreen() super.onCreate(savedInstanceState) setContent { MyTheme { Navigation() } }
闪屏结束后、第一个Composable显示前会出现一秒空白屏。移除Navigation直接使用ComposableScreen时,无空白屏问题。我的Navigation代码如下:
@Composable fun Navigation( modifier: Modifier = Modifier, navController: NavHostController = rememberNavController(), startDestination: String = ScreenRoutes.Ls.route, ) { NavHost( modifier = modifier, navController = navController, startDestination = startDestination ) { composable(route = ScreenRoutes.Ls.route) { Ls() { destination -> when (destination) { ScreenRoutes.Ms-> { navController.navigate(destination.route) { popUpTo(0) } } ScreenRoutes.Fp-> { navController.navigate(destination.route) } ScreenRoutes.Ls-> {} ScreenRoutes.Sc-> { navController.navigate(destination.route) } ScreenRoutes.Up -> navController.navigateUp() } } } composable(route = ScreenRoutes.Sc.route) { Sc() { destination -> if (destination == ScreenRoutes.Up && navController.previousBackStackEntry != null) { navController.navigateUp() } else { navController.navigate(destination.route) { popUpTo(0) } } } } composable(route = ScreenRoutes.Ms.route) { Ms() { } } composable(route = ScreenRoutes.fg.route) { ForgotPassword() { destination -> if (destination == ScreenRoutes.Up && navController.previousBackStackEntry != null) { navController.navigateUp() } else { navController.navigate(destination.route) } } } } }
已尝试开启minify和proguard的release版本,空白屏问题略有改善但仍存在。需要可行的优化方案,或让闪屏直到组合完成后再消失的方法。
优化方案
1. 控制闪屏直到Compose初始化完成
利用SplashScreen API的setKeepOnScreenCondition方法,让闪屏保持显示直到Compose完成首次组合和绘制:
override fun onCreate(savedInstanceState: Bundle?) { val splashScreen = installSplashScreen() super.onCreate(savedInstanceState) var isComposeReady by mutableStateOf(false) setContent { MyTheme { // 首次组合完成后标记就绪 LaunchedEffect(Unit) { // 可在此添加必要的异步初始化操作(如预加载数据) isComposeReady = true } Navigation() } } // 闪屏保持显示的条件:Compose未就绪 splashScreen.setKeepOnScreenCondition { !isComposeReady } }
2. 优化Navigation启动性能
- 轻量化启动页面
Ls():检查Ls()是否在初始组合时执行了同步耗时操作(如复杂计算、同步IO),将这些操作移到LaunchedEffect中异步执行,避免阻塞UI线程。 - 避免预加载非启动页面:NavHost默认会提前处理部分页面的状态,可通过简化页面间的过渡动画(如暂时禁用
enterTransition)减少启动时的计算开销。 - 优化主题初始化:如果
MyTheme包含自定义字体加载、动态主题计算等逻辑,将这些操作异步化,比如用remember配合LaunchedEffect加载字体,避免阻塞主题初始化。
3. 预加载关键资源
在闪屏阶段提前初始化Compose所需的关键资源,减少启动时的等待:
override fun onCreate(savedInstanceState: Bundle?) { val splashScreen = installSplashScreen() super.onCreate(savedInstanceState) var isReady by mutableStateOf(false) // 提前初始化NavController,避免在Compose中重复创建 val navController = rememberNavController() setContent { MyTheme { // 预加载自定义字体等资源 val customFont = remember { FontFamily(Font(R.font.app_font, FontWeight.Normal)) } LaunchedEffect(customFont) { // 等待资源加载完成后标记就绪 isReady = true } Navigation(navController = navController) } } splashScreen.setKeepOnScreenCondition { !isReady } }
4. 分析并优化UI绘制耗时
使用Android Studio的Compose Profiler或Layout Inspector分析启动过程中的UI绘制耗时,定位Ls()或Navigation中导致延迟的布局、Modifier或状态计算逻辑,针对性简化优化。
内容的提问来源于stack exchange,提问作者joghm
相关产品推荐
相关产品推荐

