【问题标题】:"Lateinit property has not been initialized" error on a variable initialized in onCreateView在 onCreateView 中初始化的变量出现“Lateinit 属性尚未初始化”错误
【发布时间】:2020-09-18 05:03:15
【问题描述】:

我正在开发的应用程序包含三个类。 MainActivity(此处不重要)、MyFragmentMyClass。 我在MyFragment 中有一个lateinit 列表——它是lateinit,因为它会被某些方法使用。 (顺便说一下,我使用的是 kotlin 合成)

class MyFragment: Fragment()
    lateinit var myViewsList: List<View>
    lateinit var viewA: View
    lateinit var viewB: View
    lateinit var viewC: View

    override fun onCreateView(
    //inflating the layout...
    ): View? {
        val view = inflater.inflate(R.layout.fragment_timer, container, false)

        val button: Button = view.myButton
        viewA = view.myViewA
        viewB = view.myViewB
        viewC = view.myViewC

        myViewsList =
            listOf<View>(viewA,viewB,viewC) 

        myButton.setOnClickListener() {
            MyClass().myMethod()
        }

        return view
    }

然后MyClass:

class MyClass() {
    fun showViews {
        MyFragment().myViewsList.forEach { // this line is causing the error
            it.visibility = View.VISIBLE
        }
    }

    fun myMethod() {
        //do some stuff
        //delay...
        showViews()
    }


}

但是,每当调用showViews() 时,我都会收到“lateinit property myViewsList not initialized”错误(并且在片段被销毁、启动或类似情况时不会调用它。在我的应用程序中,它会带你~ 10 秒调用它——为了简单起见,我只是把它放在 OnClickListener 中——在这 10 秒内没有任何活动变化)。

我不明白为什么,因为它在 OnCreateView myViewsList = listOf&lt;View&gt;(viewA,viewB,viewC)被初始化。任何涉及myViewsList 内部MyFragment 的调用都可以正常工作,但不能在MyClass 内部调用。那么,为什么会这样呢?调用或初始化它的正确方法是什么?

【问题讨论】:

  • 查看这篇文章,它会解决你的问题:stackoverflow.com/a/46584412/9636037
  • MyFragment().myViewsList 您正在创建新的片段实例,而不是传递对现有片段的引用。
  • @Abhimanyu 嗯...它不会总是跳过我的代码中带有if (...isInitialized) 的部分 - 因为它说“...尚未初始化”?反正我会试试的。谢谢
  • 我的意思是说它会像一个空检查,但它不会解决你的问题,这并不意味着你不应该使用空检查,它们非常重要。现在,因为您在NavigationDrawer 中使用MyFragment,所以您可以传递它的引用,因此当您调用MyClass 中的列表时,您将调用已经初始化的实际列表。您在这里所做的是实际上并没有传递引用,而是创建了该片段的新引用,这显然是未初始化列表的原因。
  • 我找到了一个类似的answer,但它不适用于 NavigationDrawer,但它可以提供帮助。您可以在您的案例中使用类似的参考。

标签: android kotlin lateinit


【解决方案1】:

我在这里可能错了,但我认为 Android 片段类不会像任何其他常规类一样工作。当您调用 MyFragment().myViewsList 时,您并未调用片段的同一实例,并且当您调用尚未初始化的此变量“myViewsList”时,它会崩溃。

要使其工作,您必须传递您的列表和您希望使其可见的视图。

class MyFragment: Fragment()
    lateinit var myViewsList: List<View>
    lateinit var viewA: View
    lateinit var viewB: View
    lateinit var viewC: View

    override fun onCreateView(
    //inflating the layout...
    ): View? {
        val view = inflater.inflate(R.layout.fragment_timer, container, false)

        val button: Button = view.myButton
        viewA = view.myViewA
        viewB = view.myViewB
        viewC = view.myViewC

        myViewsList =
            listOf<View>(viewA,viewB,viewC) 

        myButton.setOnClickListener() {
            MyClass(myViewsList).myMethod()
        }

        return view
    }

你的班级应该是这样的:

class MyClass(private val views: List<View>) {
    fun showViews {
        views.forEach { // this line is causing the error
            it.visibility = View.VISIBLE
        }
    }

    fun myMethod() {
        //do some stuff
        //delay...
        showViews()
    }


}

【讨论】:

  • 所以我需要在MyClass 中再次创建这个列表(因此也是它的视图),对吧?我有一个问题,如果我初始化了myViewList,为什么没有初始化它(在onCreateView中)?还是只是在 onCreateView 中“本地”初始化?如果是这样的话,那么为什么涉及 List 的方法在 MyFragment 内部工作(但在 onCreateView 外部)?如果它是本地的,我想它应该只在 onCreateView 内部工作,而不是在外部工作。也许我在这里遗漏了一些东西。
  • 你不需要重新创建,我会用你可以做什么的样本来更新答案。它已被初始化,如果您尝试在片段内操作它,例如创建一个引用它的乐趣,它将起作用。但是你试图做的是创建一个想要初始化的新 MyFragment,片段生命周期将在你附加它时开始,所以当你像“MyFragment.list”一样调用时,你跳过了这部分因此崩溃。
  • 如果不涉及myFragment,我无法创建列表及其视图。通过将视图初始化为viewA = myFragment().myViewAviewB = ... myViewB,它会崩溃并出现以下错误"java.lang.IllegalStateException: myFragment().myViewA must not be null"
  • 谢谢。我会等待您的示例并尝试将其实现到我的代码中。
  • 现在可以使用了,谢谢!还有一个问题。如果我曾经在其他地方调用myClass 以使用它的另一种方法(这与隐藏视图无关,因此无需将任何列表传递给它),是否有办法制作“无列表”需要参数”版本?比如,只需调用myClass().someOtherMethod 而不必传递一个(在这种情况下是不必要的)列表?我考虑过不必每次调用时都传递一个列表,只需创建一个setList() 方法,该方法接收一次列表并在myFragment 上调用它。我会试试看它是否有效。
猜你喜欢
  • 2017-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-31
  • 2021-06-11
  • 2017-12-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多