Fun with setOnClickListener and by lazy

The Problem

Developing an Android app, using Android’s Navigation Components, and after returning to the first fragment, the button to go to the second fragment wasn’t working. The onClickListener wasn’t being called. I was finding the button via Kotlin’s lazy delegate:

val myButton: Button by lazy { 
  activity?.findViewById<Button>(R.id.my_button)
    ?: throw IllegalStateException("...")
}

And setting the listener in onViewCreated:

myButton.setOnClickListener { doOnClick() }

Where doOnClick() gathers a few values and navigates to the second fragment via Navigation and safeArgs.

val directions = FirstFragmentDirections.actionFirstFragmentToSecondFragment(...)
Navigation.findNavController(myButton).navigate(directions)

The problem was doOnClick() was not being called.

The Solution

After making doubly sure myButton.setOnClickListener was being called (it was) and doOnClick wasn’t, I looked at another project where I had a similar setup, but it was working. The difference? I was using a Kotlin synthetic import to find the button. Changing my code to use a synthetic ijmport instead of by lazy immediately fixed the problem.

import kotlinx.android.synthetic.main.first_fragment.my_button as myButton

SO, now I’m looking through Android’s public bug tracker to see if anyone else has had the problem. If not I’ll make a minimal app to recreate the problem, and submit it.

Leave a comment