2
votes

what is the difference or no difference in the following two approaches:

1.

private lateinit var binding: ResultProfileBinding
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ResultProfileBinding.inflate(layoutInflater)
    val view = binding.root
    setContentView(view)
}
private var _binding: ResultProfileBinding? = null
// This property is only valid between onCreateView and onDestroyView.
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    _binding = ResultProfileBinding.inflate(layoutInflater)
    val view = binding.root
    setContentView(view)
}

The above sample code are from: https://developer.android.com/topic/libraries/view-binding. one use lateinit for Activity the other use one computed property backed by optional var for Fragment.

Both seem to work in Fragment and Activity, but this get me curious: is there any differences in Kotlin language?

2

2 Answers

4
votes

The reason they do this for the Fragment example is that the Fragment views may be torn down and removed while it is detached from an Activity, and then recreated (in onCreateView()) on the same Fragment instance when it is reattached to an Activity. During the time the Fragment is detached, the original binding instance is invalid, so a nullable property (_binding) is used and set back to a null value in onDestroyView() (see the example code you linked) to avoid leaking these views when they are no longer valid.

But in most places in your Fragment code, it is safe to assume the Fragment is attached, so the binding property that returns a non-null binding is there for convenience. This is similar to requireContext() and requireActivity() which are more convenient to use than nullable context and activity. You just need to avoid using them at times when the Fragment may be detached. This could happen in asynchronous code like in the callback of some network call.

In Activity, they use lateinit because you can't initialize views before the Activity is fully constructed. Your first safe entry-point is onCreate(), so the property can be set there. lateinit allows the property to be non-nullable, yet still safe to use so long as you set its initial value at the earliest possible point, which is onCreate().

lateinit is not the right approach for Fragment, because the binding is legitimately non-existent during certain times in the Fragment's life, so you need to be able to set it to null. And for Activity, you could choose to use a nullable property instead of lateinit, but it would impractical to have to deal with its nullability when it can never be null during the time you have access to the Activity members.

1
votes

lateinit allows you to create non-nullable data objects hence why you dont see a ? next to the property. Other than that there is really no difference