You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Android 12 SplashScreen结束前Fragment提前初始化问题

问题根因

OnPreDrawListener 仅拦截界面绘制流程,不会阻塞布局加载、Fragment初始化的执行逻辑。调用setContentView时,布局中声明的NavHostFragment会立刻被实例化,从onAttach到onViewCreated的生命周期链路会正常执行,和闪屏是否展示、是否挂起绘制没有关联,必然会出现时序错位。

修复方案

方案1:延迟绑定导航图(改动最小)

  • 第一步:修改activity_main布局,移除FragmentContainerView上预配置的app:navGraph属性,不在布局加载阶段绑定导航图:
<androidx.fragment.app.FragmentContainerView
    android:id="@+id/nav_host_fragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true"
    />
  • 第二步:调整闪屏等待逻辑,仅在初始数据加载完成后,再手动给NavHostFragment设置导航图——设置navGraph的动作才会触发起始Fragment的创建和生命周期回调:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    installSplashScreen()
    setContentView(R.layout.activity_main)
    val content: View = findViewById(android.R.id.content)
    // 此时仅实例化空的NavHostFragment,不会加载任何业务Fragment
    val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController

    content.viewTreeObserver.addOnPreDrawListener(
        object : ViewTreeObserver.OnPreDrawListener {
            override fun onPreDraw(): Boolean {
                return if (mainActivityViewModel.isDataReady()) {
                    Timber.tag("Splash").d("data ready")
                    // 数据就绪后再绑定导航图,触发业务Fragment初始化
                    if (navController.currentDestination == null) {
                        navController.setGraph(R.navigation.nav)
                    }
                    content.viewTreeObserver.removeOnPreDrawListener(this)
                    true
                } else {
                    Timber.tag("Splash").d("data not ready")
                    false
                }
            }
        }
    )
}

代码中加currentDestination == null判断是为了避免Activity重建(旋屏、系统后台回收)时重复设置导航图,引发状态异常。

方案2:延迟添加NavHostFragment(隔离更彻底)

如果不希望在数据加载阶段实例化任何导航相关组件,可以把activity_main初始布局设为不带FragmentContainerView的空根容器,等数据加载完成后,再通过FragmentTransaction动态添加NavHostFragment并绑定导航图。这种方案能做到数据就绪前完全不触发任何业务Fragment的生命周期,适合初始化逻辑重、对启动时序要求极高的场景。

避坑提示

不要在Fragment生命周期中加主线程阻塞逻辑等待数据,这类操作会卡住主线程,轻则触发ANR,重则导致Fragment状态保存/恢复异常。所有依赖启动初始数据的Fragment逻辑,必须保证在数据就绪后再触发初始化。

内容的提问来源于stack exchange,提问作者hushed_voice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 15:15:33