Caution with lateinit and Android

lateinit vars seem to suggest itself for certain things when programming for Android, like:

  • fields for views that are available after they have been inflated in onViewCreated
  • fields for non-optional arguments that have been passed to the fragment in onCreate

I did it this way but now came across a race condition where a parent fragment would try to query a lateinit field of a child fragment (via childFragmentManager.findFragmentByTag(...)?.thatOneLateinitFieldThatIsInitializedInOnCreate and failed because the lateinit field was not initialized yet.

So apparently, a parent fragment can find a child fragment before onCreate on the child fragment has been called. This design makes it problematic to use any lateinit var for the above mentioned use cases.

Kotlin Is not Java, there is very little reason to keep using reassignable variables. Use lazy delegation and vals.

Have a look at this project for examples. The module ‘app’ is what you are looking for.

2 Likes

I suppose you mean

private val foo: String by lazy { requireArguments().getString(ARG_FOO)!! }

Right, so lateinit can be avoided in this case. Though, this has the downside that it does not fail fast when a required argument is not passed (or something wrong is passed).

Well, the error you are trying to fix is not language related but resides in the logic of your application.
If the arguments are the ones needed to launch a fragment, use the Android navigator; if for an activity, check out how I statically parametrized the activity launch in the app I linked you.

1 Like