android - 在 Android 12 启动画面结束之前 fragment 被初始化

标签 android android-fragments android-lifecycle android-splashscreen

我的 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" />

我希望我的 fragment 等到我从 API 获取一些数据后再隐藏启动屏幕。我正在使用 Android 12 Splash Screen 。这就是我试图实现它的方式(来自 documentation ):

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
                        }
                    }
                }
        )

只有在我获取数据后,启动屏幕才会消失。但问题是,即使在我的数据准备好之前,我的 Fragments 回调(例如 onViewCreated)也会被调用。这会导致问题,因为我依赖在启动屏幕期间获取的数据来执行某些任务。

我如何确保在我的启动屏幕消失之前我的 fragment 不会被初始化?

最佳答案

The Splash screen is going away only after I get the data. But the issue is that my Fragments callbacks like onViewCreated gets invoked even before my data is ready.

Activityfragment生命周期回调仅由系统在适当的时间触发。它们不能由开发人员触发;对此无法控制。因此,您无法阻止 onCreateViewonViewCreated 等发生。即,您无法从初始化中停止 Activity/fragment ;否则您可能会出现 ANR。

更详细

在某些后台任务完成之前,不应捕获 Activity/fragment 的初始化;这确实会导致 ANR。

当您使用addOnPreDrawListener获取 Activity 根布局的绘制时;这并不意味着 Activity 的初始化(即 onCreate())被捕获,因为两者都是异步工作的,并且 onCreate()onStart() , & onResume() 会正常返回。

对于 fragment 的回调也是如此,其中 fragment 的初始化(即 onCreateView()onViewCreated...)与 Activity 的 onCreate() 耦合.

现在,由于起始目标 fragment 的初始化依赖于API数据;那么这个特定的 fragment 不应该是起始目的地。

因此,要解决此问题,您需要创建一些启动屏幕 fragment 作为不依赖于 API 数据的起始目标。

根据 API 传入数据,您可以通过 navController 决定导航到原始 fragment :

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
        }
    }
}

关于android - 在 Android 12 启动画面结束之前 fragment 被初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72578802/

相关文章:

java - Android Java应用程序重复执行

android - 如何为图表引擎条形图中的每个条形分配空间?

java - Android Fragment 未从界面更新图像

android - fragment 上的更改列表正在其他 fragment 中更改

java - 在 Android Studio 中迁移到 AndroidX 后出现 YoutubeAndroidPlayerAPI 错误

android - Facebook SDK 与 Android 中的 fragment 集成?

android - 再次在 Activity 生命周期 : onStart is called when it shouldn't be

java - Android 写入 SDCARD 问题?

android - 使用 SimpleCursorAdapter 和 ViewBinder 在 ListView 项中设置图像

java - GSON : Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $