DEV Community

Cover image for Working with ViewBinding in Android using Kotlin
Aayush Gupta
Aayush Gupta

Posted on • Updated on

Working with ViewBinding in Android using Kotlin

Android uses XML to create GUI components for applications. Most developers use findViewById to communicate with the GUI components since the beginning.

However, the Jetpack framework also has another great way to communicate with GUI components which is ViewBinding.

ViewBinding offers null and types safety over findViewById which are great benefits for developers to reduce multiple issues during runtime.

Usage

Enabling Support

To use ViewBinding, you need to declare it as supported in your module-level build.gradle file under the android section.

android {
    buildFeatures {
        viewBinding true
    }
}
Enter fullscreen mode Exit fullscreen mode

Android Studio will prompt you to sync Gradle changes with the project. Doing it will generate a binding class for every layout file in the module. We will use these generated classes to communicate with the GUI components.

Using in Activity

Now head over to your file containing Activity in which you want to use ViewBinding. In my case, I will use MainActivity as an example.

Here is how my MainActivity.kt file looks right now:

package dev.theimpulson.viewbinding

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, to use ViewBinding, declare a private lateinit var of type ActivityMainBinding. You can notice that the binding type is named after the layout used to generate the specific binding.

private lateinit var binding: ActivityMainBinding
Enter fullscreen mode Exit fullscreen mode

Now to get an instance of the activity, modify the onCreate method to create an instance of the AcitvityMainBinding with inflate method.

binding = ActivityMainBinding.inflate(layoutInflater)
Enter fullscreen mode Exit fullscreen mode

Now you can use this binding variable to access the GUI components. Modify the setContentView to use the ViewBinding as well. This can be done by using root property.

setContentView(binding.root)
Enter fullscreen mode Exit fullscreen mode

Here is how my MainActivity.kt looks after enabling support for ViewBinding:

package dev.theimpulson.viewbinding

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import dev.theimpulson.codepurviewbinding.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }
}
Enter fullscreen mode Exit fullscreen mode

and that's it. Now your Activity class is ready to use ViewBinding to communicate with the GUI components. Just call the components using their id as property on the binding variable you created earlier and you can perform functions you want to.

Using in Fragments

Using ViewBinding in Fragments is also similar to Activities except for the fact that you need to set the binding to null onDestroyView. In case you are wondering why is that, here is a good answer on StackOverflow regarding this different treatment.

I am reading ListFragment source code and I see this implementation:

ListAdapter mAdapter;
ListView mList;
View mEmptyView;
TextView mStandardEmptyView;
View mProgressContainer;
View mListContainer;
CharSequence mEmptyText;
boolean mListShown;

/**
 * Detach from list view.
 */
@Override
public void onDestroyView() {
    mHandler.removeCallbacks(mRequestFocus);
    mList = null;
    mListShown = false;
    mEmptyView = mProgressContainer =

I will be using my FirstFragment class to show you how you can do this. Here is how my FirstFragment.kt looks before using ViewBinding:

package dev.theimpulson.viewbinding

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment

class FirstFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_first, container, false)
    }

}
Enter fullscreen mode Exit fullscreen mode

Now, create a private var of type FragmentFirstBinding which is null as well as a private val with a getter to obtain a non-null instance of the first variable.

private var _binding: FragmentFirstBinding? = null
private val binding get() = _binding!!
Enter fullscreen mode Exit fullscreen mode

Now, modify onCreateView to instantiate your first variable to inflate the Fragment. We will use the inflater and container which onCreateView accepts as arguments to achieve this.

_binding = FragmentFirstBinding.inflate(inflater, container, false)
Enter fullscreen mode Exit fullscreen mode

Now similar to activity, we can use root property to return a view.

return binding.root
Enter fullscreen mode Exit fullscreen mode

Remember, to set the variable to null onDestroyView to ensure that view gets released once the fragment is destroyed.

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}
Enter fullscreen mode Exit fullscreen mode

Here is how my FirstFragment.kt looks after adding support for ViewBinding:

package dev.theimpulson.viewbinding

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import dev.theimpulson.codepurviewbinding.databinding.FragmentFirstBinding

class FirstFragment : Fragment() {
    private var _binding: FragmentFirstBinding? = null
    private val binding get() = _binding!!

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

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

}
Enter fullscreen mode Exit fullscreen mode

and that's all. Now you can use the binding variable to call the required GUI components to modify their behavior in your Fragment class as well.

Top comments (2)

Collapse
 
jcarlosr profile image
Juan Ramos • Edited

For Fragments:
Do we need a nullable instance and a getter?

What about using lateinit like the following?
private lateinit var binding: MyClassBinding

Collapse
 
robiabo profile image
Robiabo

Hello, can you please help me with this?
dev.to/robiabo/margin-indentation-...