Android View Binding

Android View binding

View binding is a feature that allows you to more easily write code that usage views. When view binding is enabled for each XML layout a binding class is generated. An instance of the binding class contains direct references to all views with a id, is Null-safe and Type-safe.

In most cases, view binding replaces findViewById and direct usage of R.layout resources to reduce boilerplate.

But how about extern libraries as ButterKnife or Kotlin synthetics, View Binding is more safe and runs compile time instead of runtime.

View binding is supported since Android Gralde Plugin 3.6 (From Android Studio 3.6) released in February 2020 for both Java and Kotlin

How to enable view binding

No extra libraries are needed for View binding.View binding is module based and need to be configured for each module.
This can be done by adding the ViewBinding element in the build.gradle file, see below example.

View binding the basics

After enabling view binding inside the module, a binding class is generated for each XML layout file, no extra flags or options are needed. This binding class contains reference to the root view and all views with an ID. The name of the binding class is generated by id label to camel case and adding the postfix "Binding".
The generated binding class is directly usable inside any Activity, Fragment, RecyclerView or any other custom view.

How does a generated view binding layout look?

Below layout will generate a ContentMainBinding.java which contains all views.
The views are by default with the correct type and null-safety
.
Path: <module>\build\generated\data_binding_base_class_source_out\debug\out\com\example\myapplication\databinding\ContentMainBinding.java

View bindings with Activities

With view binding no longer R.layout or R.id references, which are checked only at runtime, are needed to setup layouts.
By calling ContentMainBinding binding = ContentMainBinding.inflate(getLayoutInflater()); the binding is created.
By calling setContentView(binding.getRoot()); the view is inflated at top level op the activity view.

See below code example with the original and view binding way of working for activities:

View bindings with Fragments

For fragments the same logic is applied as for activities. No longer R.layout or R.id references are used, but directly the generated binding class. Remember that for fragments that a root element is needed, this is provided by onCreateView(). To respect Android lifecycle we need to set decouple the binding in onDestroyView

See below code example with the original and view binding way of working for fragments

View binding with RecyclerViews

Are you still using the RecyclerView.Adapter? Take a look at the latest ListAdapter

For RecyclerViews the view binding is almost the same, but there are a few difference.

Within the onCreateViewHolder a new binding reference is created and provided in the ViewHolder. The use this binding during bindTo where the view and data are combined.

But now all layouts are marked as UnusedResources!

By default lint does not check within generated sources, so within the project there is indeed no reference between source code and the layout files. To solve this issue add the lintOptions.checkGeneratedSources = true within build.gradle.
This may generate some RestrictedApi lint warnings due generated files. Simply add / extend the lint.xml file inside the module folder

<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="RestrictedApi" severity="error">
<ignore path="build" />
</issue>
</lint>

With above configuration the invalid UnusedResources lint warnings are gone and we can focus on the actual lint issues. More background information about lint: Android Lint

Links

Thank you for reading this article, If you liked the article, help others find this article by sharing it

Reacties

Populaire posts van deze blog

Android-x86 virtual machine configuration tips

Android and SonarQube with code coverage

Setup SonarQube with Docker