Reusability in Android (Kotlin) — Fragment with Data Binding

Manav Tamboli
3 min readMar 31, 2021

Adding data binding to fragments can be a bit tedious, especially when using the Single Activity Architecture.

In the official documentation, the preferred way to apply view binding in your fragment is as follows:

And the same goes for Data Binding. In this article, we will try removing all the boilerplate code needed for adding Data Binding in our fragments.

Objective

Create a base fragment class supporting Data Binding.

What Changes

On taking a look on the above code, it can be noticed that the only thing changing from fragment to fragment will be the Data Binding Class and the binding Inflate Method.

Step 1:

First of all , let’s create a base fragment class — FragmentX , with a binding variable. But, we need to specify a Data Binding Class Type for the binding variable, which will keep changing from fragment to fragment. So, to make this reusable, we can take the help of Kotlin Generics.

Step 1

Here, we took a Type Parameter with an Upper bound of class ViewDataBinding, which is the base class for all the generated data binding classes. Adding an upper bound will force to use only Data binding classes and not some other random class.

Step 2:

We use the static inflate method which is available in the generated data binding classes. As the method is generated, we cannot use it in our FragmentX . Because, the only thing we know about our type parameter is that it is inherited from ViewDataBinding, and there is no inflate method directly available in that class.

But, there is a method in DataBindingUtil class which can help us inflate our binding using a Layout Resource Id. See DataBindingUtil.inflate.

Step 2

Now, we have both the Data Binding Class and Inflate method in the FragmentX. In the next step, let’s complete the implementation.

Step 3:

Let’s add a helper property for the binding variable and implement the Fragment.onDestroyView()

Step 3

Our FragmentX is almost ready to use, but we can still extend this to make our code more tidy.

Step 4:

Usually, when we need some initializations in our binding, we do it right after inflating, that is, in Fragment.onCreateView, as below:

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {    _binding = DataBindingUtil.inflate(inflater, layoutResId, container, false)

// Initializations
binding.var1 = 0
binding.var2 = "abcdefg"
doSomethingElse()
return binding.root
}

To do this in the inherited fragments, you will have to do something like this:

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {    val view = super.onCreateView(infater, container, savedInstanceState)

doInitializations()
return view
}

Still, it is some boilerplate code. To fix this, we can add an extension function which can be optionally overriden in the child fragments.

Step 4

Using the T.initialize(), there will be no need to override Fragment.onCreateView to do initializations.

Usage

Usage

Alternatives

Kotlin Lazy Delegates with a lifecycle observer, can also be used to remove some boilerplate code, but still you need to override the methods in the fragment. In my opinion, creating a base fragment class is a better way than creating a lazy delegate.

End Notes

The FragmentX covers the usual implementation of Fragment + Data Binding, but you can always modify it to meet your requirements.

--

--