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
}
}
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)
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)
}
}
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)
}
}
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)
Now similar to activity, we can use root property to return a view.
return binding.root
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
}
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
}
}
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)
For Fragments:
Do we need a nullable instance and a getter?
What about using
lateinit
like the following?private lateinit var binding: MyClassBinding
Hello, can you please help me with this?
dev.to/robiabo/margin-indentation-...