View Binding in Android.
Tags: android, java, kotlin, codenewbie
Published: 2022-01-03 16:31:14

If you're familiar with native Android app development with either [Java](https://www.java.com/en/) or [Kotlin](https://kotlinlang.org/), then you've probably needed a means by which to write code that interacts with your views, which would have probably been written in an [XML layout file](https://developer.android.com/guide/topics/ui/declaring-layout). Well, to make things simpler, that's where [View Binding](https://developer.android.com/topic/libraries/view-binding) comes right in.

For starters, according to the official Android developer resource:

> View binding is a feature that allows you to more easily write code that interacts with views.

Once view binding is enabled in a module, it generates a _binding class_ for each XML layout file present in that module. An instance of a binding class contains direct references to all views that have an ID in the corresponding layout.
In most cases, view binding replaces `findViewById`. This simply means that you are essentially able to get rid of the excess boilerplate code. 
Without wasting any more time, let's get straight to the code.

![GIF](https://media.giphy.com/media/tJDz8mPYyUJZ1Pg9fA/giphy.gif)

## Setting it up.

Fun fact: You don't need to include any extra libraries to enable view binding, as it's built into the Android Gradle Plugin starting with the versions shipped from Android Studio 3.6 onwards. To enable view binding, configure `viewBinding` in your module-level `build.gradle` file.

```
android {
    ...
    buildFeatures {
        viewBinding true
    }
}
```
Once enabled for a project, view binding will generate a binding class for all of your layouts automatically. The name of the binding class is generated by converting the name of the XML file to Pascal case and adding the word "Binding" to the end.
Once this is done, you can use the binding class whenever you inflate layouts such as `Fragment`, `Activity`, or even a RecyclerView `Adapter` (or `ViewHolder`).

## View Binding in an Activity.
To set up an instance of the binding class for use with an activity, you have to perform the following in the activity's [`onCreate()`](https://developer.android.com/reference/kotlin/android/app/Activity#oncreate) method:

1. Call the static `inflate()` method included in the generated binding class. This creates an instance of the binding class for the activity to use.
2. Get a reference to the root view by either calling the `getRoot()` method or using [Kotlin property syntax](https://kotlinlang.org/docs/properties.html#declaring-properties).
3. Pass the root view to [`setContentView()`](https://developer.android.com/reference/kotlin/android/app/Activity#setcontentview_1) to make it the active view on the screen.

```
private SampleLayoutBinding binding;
private TextView categoryName;
private Button submitButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = SampleLayoutBinding.inflate(getLayoutInflater());
    View view = binding.getRoot();
    setContentView(view);
    init();
}
private void init() {
    categoryName = binding.categoryName;
    submitButton = binding.submitButton;
}
```
Once this is done, you can now use the instance of the binding class to reference and utilize any of the views:

```
categoryName.setText(categoryList.get(category_index).getName());
submitButton.setOnClickListener(v -> submitTest());

```

## View Binding in Fragments.
To set up an instance of the binding class for use with a fragment, you have to perform the following in the fragment's [`onCreateView()`](https://developer.android.com/reference/kotlin/androidx/fragment/app/Fragment#oncreateview) method:

1. Call the static `inflate()` method included in the generated binding class. This creates an instance of the binding class for the fragment to use.
2. Get a reference to the root view by either calling the `getRoot() `method or using [Kotlin property syntax](https://kotlinlang.org/docs/properties.html#declaring-properties).
3. Return the root view from the `onCreateView()` method to make it the active view on the screen.

```
private SampleLayoutBinding binding;
private TextView categoryName;
private Button submitButton;

@Override
public View onCreateView (LayoutInflater inflater,
                          ViewGroup container,
                          Bundle savedInstanceState) {
    binding = SampleLayoutBinding.inflate(inflater, container, false);
    View view = binding.getRoot();
    init();

    return view;
}

private void init() {
    categoryName = binding.categoryName;
    submitButton = binding.submitButton;
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    binding = null;
}
```

Once this is done, you can now use the instance of the binding class to reference and utilize any of the views:

```
categoryName.setText(categoryList.get(category_index).getName());
submitButton.setOnClickListener(v -> submitTest());
```

## ViewBinding in a RecyclerView Adapter(or ViewHolder).
To set up an instance of the binding class for use with a RecyclerView Adapter, you need to pass the generated binding class object to the holder class constructor. In your example, you may have `recipe_card` XML file for `RecyclerView` item and the generated class is `RecipeCardBinding` . 
Therefore, you need to use the `onCreateViewHolder` to pass the generated binding class to the `ViewHolder` class.

```
@NonNull
@Override
public CategoryAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    RecipeCardBinding itemBinding = RecipeCardBinding .inflate(LayoutInflater.from(parent.getContext()), parent, false);
    return new ViewHolder(itemBinding);
}
```
Once the above steps have been completed, you may then use the holder class like this so you can use these fields in `onBindViewHolder`.

```
static class ViewHolder extends RecyclerView.ViewHolder {
    private TextView textView;
    private ImageView imageView; 

    MyViewHolder(RecipeCardBinding itemBinding) {
        super(itemBinding.getRoot());
        imageView = itemBinding.img ;
        textView = itemBinding.txt ;
    }
}
```

---

All in all, View Binding is a pretty good solution when it comes to binding views as they are:

- **Type-safe:** Properties are always correctly typed based on the views in the layout. So if you put a `TextView` in the layout, view binding will expose a `TextView` property.
- **Null-safe:** This is applicable for layouts defined in multiple configurations. View binding will detect if a view is only present in some configurations and create a `@Nullable` property.

And since the generated binding classes are regular Java classes with Kotlin-friendly annotations, you can use view binding from both the Java programming language and Kotlin.

## Differences between findViewById(), Butterknife, Kotlin Synthetics, DataBinding, and View Binding.


![Courtesy of https://wajahatkarim.com/](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nb46qswk8evx5fbl5xo1.png)

## Resources.
In case you may need further information on View Binding or any of its alternatives, then these links will be of much help:

- https://developer.android.com/topic/libraries/view-binding#java
- https://medium.com/androiddevelopers/use-view-binding-to-replace-findviewbyid-c83942471fc
- https://wajahatkarim.com/2020/04/evolution-of-finding-views/

---
That was indeed all that I have to share for now✌. To all readers, cheers to code🥂, and have a blessed day.