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 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) >>
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
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)
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)
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) >>
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.
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) >>
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!!
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)
Remember, to set the variable to null onDestroyView to ensure that view gets released once the fragment is destroyed.
override fun onDestroyView()
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 >>
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.