Kotlin: Declaration Order matters

1 minute read

I encountered a NPE implementing the new Android ViewModel class recently. Fixing the problem took a little longer due something I didn’t understand about Kotlin until now. Declaring class member values after the init block will not be initialised when the init block is executed. Example:

class MyClass {
    init {
        updateAnswer("42")
    }

    val answer by lazy { MutableLiveData<String>() }

    fun updateAnswer(newAnwser: String) {
        answer.value = newAnwser
    }
}

This will cause a NPE as as the answer delegate has not been initialised in the init block. Attempting to do this:

class MyClass {
    init {
        answer.value = "42"
    }

    val answer by lazy { MutableLiveData<String>() }

}

will be caught by the editor and compiler. This can be easily fixed by changing the order in which you declare the data member.

class MyClass {
    val answer by lazy { MutableLiveData<String>() }
    init {
        updateAnswer("42")
    }

    fun updateAnswer(newAnwser: String) {
        answer.value = newAnwser
    }
}

This time the answer delegate will be set in the init block

Thanks for reading, but I would like to point out that the example where I caught this was more complicated than this simplified example. My example was using Eventbus which I have written about in a previous post. My example looked a bit more like the following:

class MyClass {
    init {
        EventBus.getDefault().register(this)
    }

    val answer by lazy { MutableLiveData<MyDomainObject>() }

    @Subscribe(sticky = true, threadMode = ThreadMode.BACKGROUND)
    protected fun bind(newAnwser : MyDomainObject) {
        answer.value = newAnwser;
    }
}

I didn’t realise that by this time Eventbus already had a MyDomainObject and thus would call the bind() function synchronously from the EventBus.getDefault().register(this) call.

Original post

Updated: