Exploring Android View Binding in Depth

Using ViewBinding with <include>, <merge>, adapters, fragments, and activities

Somesh Kumar
Feb 13 · 4 min read

Google introduced view binding in the What’s new in Android session at Google I/O 2019.

There is a brief talk about view binding in What’s New in Architecture Components, which compares view binding with existing solutions and further talks about why view binding is better than existing solutions like data binding or Kotlin synthetics.

For me, Kotlin synthetics was working fine but all the IDs reside in a global namespace so if you are using an ID with the same name and if you import the ID from the wrong layout, you’re going to get a crash because the ID is not part of the current layout and there is no way to know this in advance unless you run your app and go to that layout.

The following article has a nice overview of problems with Kotlin synthetics.

View binding will be available in Android studio’s 3.6 stable version but if you want to try it, you need to download Android Studio 3.6 RC 3.

The main advantage of view binding is that all the binding classes are generated by the Gradle plugin so it doesn’t have an effect on build time and it has compile-time safety (which we will see in our examples).

Let’s start by enabling view binding. We need to add the following in our module’s build.gradle file:

android {
viewBinding {
enabled = true

Note: View binding is enabled on a module-by-module basis so you need to add the above code in every build.gradle file if you have a multi-module project setup.

If you want to disable the view binding specific layout then you need to add tools:viewBindingIgnore=”true” to the root view of the layout file.

After enabling, we can start using it right away and all the binding classes are generated by default when you finish syncing your build.gradle file.

It generates a binding class by converting the XML layout file name to the camel case and adding Binding at the end of it. For example, if your layout file is named activity_splash then it will generate the binding class as ActivitySplashBinding.

How Do I Use It?

In activity

We have our layout file named activity_splash and in it, we have a TextView with ID tvVersionName so when using view binding, all we have to do it get the reference of the binding class, like:

val binding: ActivitySplashBinding = ActivitySplashBinding.inflate(layoutInflater) 

And use its getRoot() in the setContentView() method which returns the root layout of our layout. Views will be accessible from the binding class object we created and we can use it right after creating the object like this:

binding.tvVersionName.text = getString(R.string.version)

Here, the binding class knows that tvVersionName is a TextView so we don't have to worry about typecasting.

In fragment

Using view binding is a little different in fragments. We need to pass LayoutInflator, ViewGroup, and an attachToRoot boolean variable which we get by overriding onCreateView().

We also need to return the view which we can do by returning the root view by calling binding.root. You also noticed that we are using two different variables and the _binding variable is set to null in onDestroyView().

That’s because the fragment’s lifecycle is different from the activity’s and the fragment can outlive their views so we can get memory leaks if we don’t set it to null.

The other variable is there to avoid a null check with !! by making one variable nullable and the other one non-null.

In RecyclerView adapter

row_payment.xml is our item layout file for the RecyclerView’s row and that’s why the RowPaymentBinding class gets generated.

Now, all we need to do is call the inflate() method and pass the required parameters that are available inside onCreateViewHolder() and pass the generated binding class object in the primary constructor of our PaymentHolder class and pass the itemBinding.root to the RecyclerView.ViewHolder() constructor. That’s it.

Dealing With the <include>d Layout

View binding can be used with the <include> layout tag. There are usually two kinds of <include> tags included in layouts, with or without <merge>.

  • <include> without <merge>.

We need to assign <include> an ID and then use that ID to access the view inside the included layout. Let’s see an example of that.

In the above code, we included a common toolbar in our layout file and <include> has an android:id=“@+id/appbar” ID which we will use to access the toolbar from app_bar.xml and set it as our support action bar.

  • <include> with <merge>.

Sometimes we have a layout with the <merge> tag which helps to eliminate redundant view groups in your view hierarchy when including one layout within another.

And this layout is included as usual inside our layout file.

If we try to give this <include> an ID, the view binding won’t generate the ID in the binding class so we can’t access the view as we did in the case of the normal include.

In this case, we have PlaceholderBinding which is an auto-generated class for placeholder.xml (our <merge> layout file). We have to call its bind() method and pass the root view of the layout in which we included it.

Then, we can access views inside our placeholder.xml from our class like placeholderBinding.tvPlaceholder.text.

Thanks for reading. I’d love to hear from you in the comments.

Better Programming

Advice for programmers.

Somesh Kumar

Written by

Android Application Developer. Reading, Learning and Implementing everyday. Desire to learn is what keeps me going.

Better Programming

Advice for programmers.

More From Medium

More from Better Programming

More from Better Programming

More from Better Programming

More from Better Programming

Why Do Incompetent Managers Get Promoted?


Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade