View Binding: farewell to Kotlin Syntetic
Tags: android
Published: 2021-08-06 19:01:31

---
title: View Binding: farewell to Kotlin Syntetic
published: true
date: 2020-12-03 20:56:21 UTC
tags: Android
canonical_url: https://www.rockandnull.com/kotlin-android-extensions-view-binding/
---

 ![View Binding: farewell to Kotlin Syntetic](https://images.unsplash.com/photo-1484068043587-e86f6124d2ee?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MXwxMTc3M3wwfDF8c2VhcmNofDJ8fHxlbnwwfHx8&ixlib=rb-1.2.1&q=80&w=2000)

Kotlin Synthetic was one of the coolest features when I started playing with Kotlin. In the Android Java world, to get on hold of a view, you needed to use `findViewById()` and then cast to the appropriate view type. This was one of the most repetitive and boring tasks when creating a new view/screen.

Then Kotlin and its Synthetics came around. If you had a view with id `hello`, you would write `hello` and  you could access it. No boilerplate, no `findViewById`, not a thousand member variables in your class.

But it turns out that the concept was kind of too relaxed. They had a global namespace and there were no nullability checks. This meant that you were able to access `hello2` on screen 2, even though you were on screen 1, leading to inevitable crashes.

So a step back is probably the right balance. [Kotlin Android extensions](https://youtrack.jetbrains.com/issue/KT-42121) (which Kotlin Synthetic is part of) are deprecated, and the recommended way to replace them is the [View Bindings](https://developer.android.com/topic/libraries/view-binding). This has a bit more boilerplate but offers type and nullability safety.

## Set up 

In the `Android` section of your `build.gradle` add this:

```
android {
    [...]
    buildFeatures {
        viewBinding true
    }
}
```

## Auto-generation

Now when you do `Build` -> `Make project`, for every XML file you have a corresponding binding class will be generated. For instance, for your `fragment_screen_1.xml`, the `FragmentScreen1Binding` will be created. These classes contain a member variable for every child view in the XML layout.

_Tip:_ You might need to do `File` -> `Sync Project with Gradle files` to get Android Studio to recognize those generated classes.

## Create the bindings

### In Fragments

```
private var binding: FragmentScreen1Binding? = null // 2.

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

override fun onDestroyView() {
    super.onDestroyView()
    binding = null // 4.
}
```

1. Instead of the regular `inflate()` you will use the auto-generated class to inflate your view.
2. This `binding` is non-null only between `onCreateView()` and `onDestroyView()`.
3. The root view of your `fragment_screen_1.xml` layout.
4. Note that Fragments outlive their views. Clean up `binding` after destroying the inflated view for avoiding any memory leaks.

### In Activities

```
private lateinit var binding: FragmentScreen1Binding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = FragmentScreen1Binding.inflate(layoutInflater)
    setContentView(binding.root)
}
```

Similar to the fragment without the need for clean up since the inflated view is tightly associated with the activity lifecycle.

## Use the bindings

For every child view in the XML layout, there's a member variable with the same name in camel case in your `binding` variable. The views without an ID are not accessible.

```
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <TextView
    	android:id="@+id/hello_world"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
        
</LinearLayout>
```
<figcaption>fragment_screen_1.xml</figcaption>

```
binding.helloWorld.text = "Hello world!"
```
<figcaption>FragmentScreen1.kt</figcaption>

In case you were using Kotlin Synthetic, remove the imports for `kotlinx.android.synthetic.*` and replace them with the data bindings equivalents.

For further reading, check out the [official doc](https://developer.android.com/topic/libraries/view-binding) (and [Kotlin Synthetic migration guide](https://developer.android.com/topic/libraries/view-binding/migration)). If you don't enjoy Android Views, be a little more patient until [Jetpack Compose](https://dev.to/mavris/jetpack-compose-intro-basic-layouts-1e18-temp-slug-5246852) becomes stable :) Until then, happy coding!