android-fragments 在Android 12启动画面结束之前,片段正在初始化

nr7wwzry  于 2022-11-14  发布在  Android
关注(0)|答案(1)|浏览(154)

我的MainActivity中有一个使用导航图的FragmentContainerView。

<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"
    app:navGraph="@navigation/nav" />

我希望我的片段在我隐藏闪屏之前等待,直到我从API获得一些数据。我使用的是android 12 Splash Screen。这是我尝试实现它的方式(来自文档):

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    installSplashScreen()
    setContentView(R.layout.activity_main)
    //Set up an OnPreDrawListener to the root view.
    val content: View = findViewById(android.R.id.content)
    content.viewTreeObserver.addOnPreDrawListener(
        object : ViewTreeObserver.OnPreDrawListener {
            override fun onPreDraw(): Boolean {
                // Check if the initial data is ready.
                return if (mainActivityViewModel.isDataReady()) {
                    // The content is ready; start drawing.
                    Timber.tag("Splash").d("data ready")
                    content.viewTreeObserver.removeOnPreDrawListener(this)
                    true
                    } else {
                        Timber.tag("Splash").d("data not ready")
    
                        // The content is not ready; suspend.
                        false
                        }
                    }
                }
        )

启动画面只有在我取得数据后才会消失。但问题是我的片段回呼(如onViewCreated)在我的数据准备好之前就被叫用了。这会造成问题,因为我依赖于在启动画面期间取得的数据来执行某些工作。
我如何确保在闪屏消失之前我的片段不会被初始化?

kt06eoxx

kt06eoxx1#

Splash屏幕只有在我获得数据后才会消失,但问题是我的Fragments回调(如onViewCreated)甚至在数据准备好之前就被调用了。
Activityfragment生命周期回调只能由系统在适当的时间触发,开发人员不能触发;因此,你不能阻止onCreateViewonViewCreated,..的发生,也就是说,你不能阻止活动/片段的初始化;否则你可能会有ANR。

更多详细信息

在某些后台任务完成之前,不应获取活动/片段的初始化;这实际上将导致ANR。
当您使用addOnPreDrawListener获取Activity的根布局的绘图时;这并不意味着Activity的初始化(即onCreate())被占用,因为两者都是异步工作的,并且onCreate()onStart()onResume()将正常返回。
对于片段的回调也是如此,其中片段的初始化(即onCreateView()onViewCreated...)与Activity的onCreate()耦合。
现在,由于起始目的地片段的初始化依赖于API数据;则该特定片段不应该是起始目的地。
因此,要解决这个问题,您需要创建一个不依赖于API数据的启动屏幕片段作为启动目标。
根据API传入的数据,您可以决定通过navController

return if (mainActivityViewModel.isDataReady()) {
    
    // Do the transaction to the original fragment through the navController
    
    // The content is ready; start drawing.
    Timber.tag("Splash").d("data ready")
    content.viewTreeObserver.removeOnPreDrawListener(this)
    true
    
    } else {
    
        // Not transaction is needed, keep the splash screen fragment
    
        Timber.tag("Splash").d("data not ready")

        // The content is not ready; suspend.
        false
        }
    }
}

相关问题