Fragment 上的 Lateinit 属性未初始化

use*_*528 6 android fragment android-fragments android-activity kotlin

我已经编写了我的第一个 Kotlin 和 Android 应用程序,但我在这个应用程序上遇到了很多崩溃。

所有这些都与关键字相关lateinit

我遇到如下崩溃:

Caused by e.y: lateinit property coordinator has not been initialized

和:

Fatal Exception: java.lang.RuntimeException
Unable to start activity ComponentInfo{app.myapp/mypackage.myapp.Controllers.MainActivity}: e.y: lateinit property coordinator has not been initialized

Caused by e.y
lateinit property coordinator has not been initialized
myapp.com.myapp.Controllers.Fragments.Parents.MyParentFragment.getCoordinator


Run Code Online (Sandbox Code Playgroud)

例如,最后一个跟踪与我在片段上设置的变量相关,如下所示:

        fun newInstance(mainObject: MyObject, anotherObject: AnotherObject, coordinator: FragmentCoordinator): MyFragment {
            val fragment = MyFragment()
            fragment.mainObject = mainObject
            fragment.anotherObject = ticket
            fragment.coordinator = coordinator
            return fragment
        }
Run Code Online (Sandbox Code Playgroud)

片段侧面看起来像:

class MyFragment: MyParentFragment() {

     companion object {
        fun newInstance(mainObject:...)
     }

    lateinit var mainObject: MainObject
    lateinit var anotherObject: AnotherObject
    ... 
}
Run Code Online (Sandbox Code Playgroud)

我的理解是,当应用程序更改其状态(背景...)时,此 Lateinit 属性引用会丢失,一旦代码调用此变量属性为空并且应用程序崩溃...请理解,一旦创建了片段,所有这些变量都会丢失不为空,它们被分配。

我找到了这篇文章:https://www.bignerdranch.com/blog/kotlin-when-to-use-lazy-or-lateinit/它指示发生了什么,并且可以使用将变量链接到应用程序生命周期来修复by lifecycleAwareLazy(lifecycle) thing is at the ends of the article he adds: These two property delegates solve one problem, but not completely. They still contain a memory leak. Why does he says "they still contains memory leaks ?"

那么在android上我如何确保我的变量总是被设置,无论应用程序从后台返回还是其他什么,因为当应用程序显示片段时会发生这种情况,一些代码运行良好,然后需要调用这个lateinit变量并崩溃因为这个变量不再存在,但在创建片段时就存在。

感谢您的任何帮助。

Paw*_*wel 6

当您的活动被重新创建时,FragmentManager调用每个附加的 0 参数构造函数Fragment来重新创建它们。

您的newInstance方法应该只创建Bundle并使用它,Fragment.setArguments(Bundle)因为这是确保这些参数在配置更改中幸存的唯一方法。然后onCreate你可以在里面getArguments检索它Bundle

如果您需要无法放入 a 中的参数Bundle,则必须在 FragmentsonCreate或其他方法中注入/重新创建/获取它们。