androidkotlinlateinit

"Lateinit property has not been initialized" error on a variable initialized in onCreateView


The app I'm developing has three classes. MainActivity (not important here), MyFragment and MyClass. I have a lateinit List inside MyFragment - it is lateinit because it will be used by some methods. (I'm using kotlin synthetics by the way)

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
    }

And then 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()
    }


}

But I get the "lateinit property myViewsList not initialized" error whenever showViews() is called (and it isn't called when the fragment is destroyed, started or something like that. In my app, it'd take you ~10 seconds to call it - I've just put it in a OnClickListener for simplicity - and there aren't any activity changes during those 10 seconds).

I don't understand why, as it is initialized in OnCreateView myViewsList = listOf<View>(viewA,viewB,viewC). Any calls involving myViewsList inside MyFragment work just fine, but not inside MyClass. So, why is this happening? and what would be the correct way of calling or initializing it?


Solution

  • I may be wrong here, but I dont think an Android fragment class will work as any other regular class. When you are invoking MyFragment().myViewsList you are not calling the same instance of your fragment and as you are calling this variable "myViewsList" that hasnt been initialized, it crashes.

    To make it work, you will have to pass your list and the view that would you like to make it visible.

    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
        }
    

    and your class should be like this:

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