Android使用Splash Screen Api+导航组件遇闪屏问题求解决方案
问题解决思路
一、根据Fragment ViewModel状态控制闪屏显示
你当前代码直接用Fragment的homeViewModel会有问题——闪屏初始化时Fragment还没创建,ViewModel也没实例化,而且Fragment的ViewModel生命周期绑定到Fragment,不适合用来控制Activity级的闪屏。给你两个可行方案:
方案1:把加载逻辑移到Activity级ViewModel
- 新建一个Activity级的
LaunchViewModel,专门管理启动阶段的加载状态,要么把首页数据加载逻辑迁到这里,要么让它协调Fragment ViewModel的状态:
// 1. 定义启动状态ViewModel class LaunchViewModel : ViewModel() { private val _launchState = MutableLiveData<LaunchState>() val launchState: LiveData<LaunchState> = _launchState // 监听Fragment的ViewModel状态,转换为启动状态 fun bindHomeState(homeViewModel: HomeViewModel) { homeViewModel.homeCollectionState.observeForever { state -> _launchState.value = when (state) { is HomeCollectionState.Loading, is HomeCollectionState.Idle -> LaunchState.Loading else -> LaunchState.Ready } } } } sealed class LaunchState { object Loading : LaunchState() object Ready : LaunchState() } // 2. 在MainActivity中使用 class MainActivity : AppCompatActivity() { private lateinit var launchViewModel: LaunchViewModel private lateinit var homeViewModel: HomeViewModel override fun onCreate(savedInstanceState: Bundle?) { // 第一步必须调用installSplashScreen,不能延后 val splashScreen = installSplashScreen() super.onCreate(savedInstanceState) launchViewModel = ViewModelProvider(this)[LaunchViewModel::class.java] // 初始化HomeViewModel(如果是Navigation管理的Fragment,也可以通过NavHost获取) homeViewModel = ViewModelProvider(this)[HomeViewModel::class.java] launchViewModel.bindHomeState(homeViewModel) // 设置闪屏保持条件:只要还在加载/空闲状态就保持显示 splashScreen.setKeepOnScreenCondition { launchViewModel.launchState.value == LaunchState.Loading } setContentView(R.layout.activity_main) // 初始化Navigation等后续逻辑 } }
方案2:用LiveData跨组件传递状态
如果不想迁移逻辑,可以让Fragment的ViewModel暴露一个LiveData,然后在MainActivity中通过Activity级的ViewModel作为中介来观察这个状态。不过要注意,必须确保Fragment创建后状态能正确传递,避免闪屏提前消失。
二、必须在MainActivity调用installSplashScreen的原因
这是Splash Screen API的硬性要求:必须在super.onCreate(savedInstanceState)之后、setContentView()之前调用installSplashScreen(),否则系统会因为闪屏过渡的初始化流程缺失而崩溃。
闪屏是Activity层面的系统组件,负责衔接系统启动闪屏和应用内容,所以只能在宿主Activity(也就是你的MainActivity)中调用,不能放到Fragment里。你完全不用放弃这个API,只要遵守调用时机就行。
总结
不用自定义Fragment闪屏,只要把闪屏的状态控制逻辑放到Activity级的ViewModel中,同时按要求在MainActivity的onCreate开头调用installSplashScreen(),就能解决你遇到的两个问题。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

