Android View Binding Without Boilerplate — Part 1

Trevor Hackman
2 min readDec 12, 2021

--

View Binding is a great feature inspired by Butter Knife that replaces findViewById and Kotlin synthetics. For each XML layout a corresponding Binding class will be generated that bridges the gap between your Kotlin and XML.

The problem is there’s a little extra boilerplate you have to put in every fragment in order to properly use it according to the android documentation.

private var _binding: ProfileBinding? = null
private val binding get() = _binding!!

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = ProfileBinding.inflate(inflater, container, false)
return binding.root
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}

First of all we need to declare two bindings, a _binding and binding. This may look very strange to those unfamiliar with it, but this is a Kotlin pattern called backing properties. The purpose of it here is to have a property that is in a sense lateinit but also nullable. And the other annoying thing is having to null binding in onDestroyView to follow safe cleanup practices.

With delegates we can avoid the need for backing properties. And with lifecycle observers the days of having to write boilerplate to cleanup resources at steps of the lifecycle should be over. And that’s what I’m going to show you how to do, see below.

private var binding: ProfileBinding by nullOnDestroy()override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = ProfileBinding.inflate(inflater, container, false)
return binding.root
}

That’s it! Only one binding and we don’t even need an onDestroyView anymore. Here is the code.

Note that this isn’t coupled to View Binding in any way. If there’s anything at all that you need to null on destroy, then you can use this delegate for it.

Fragments (due to bad design) have two lifecycles: lifecycle and viewLifecycle. lifecycle ranges from onCreate to onDestroy whereas viewLifecycle ranges from onCreateView to onDestroyView. viewLifecycle is above and beyond the more important lifecycle and the one you want to pay attention to whereas you can largely ignore the other one.

The only slightly tricky thing going on here is in the init block. We’re observing viewLifecycleOwnerLiveData and then within the observe observing it.lifecycle which in this case is the viewLifecycle. A fragment’s viewLifecycle is null and not available until onCreateView happens, but luckily viewLifecycleOwnerLiveData exists and will tell us when viewLifecycle becomes available. Note there is no need to remove the observer because a fragment’s viewLifecycle is correspondingly nulled and no longer available after onDestroyView. In fact trying to access viewLifecycle outside the view lifecycle results in an IllegalStateException.

Checkout part 2 for more.

--

--

Trevor Hackman
Trevor Hackman

Written by Trevor Hackman

Hi, I am an Android developer.

No responses yet