View Binding
View binding is a feature that makes it easier to write code that interacts with views. When view binding is enabled in a module, it generates a binding class for each XML layout file that exists in that module. An instance of a bound class contains a direct reference to all views that have ids in the corresponding layout.
In most cases, a View Binding replaces findViewById.
Set up the
View binding is enabled on a module – by – module basis. To enable viewBinding in a Module, set the viewBinding build option to true in the module-level build.gradle file, as shown in the following example:
android {
...
buildFeatures {
viewBinding true
}
}
Copy the code
If you don’t need to generate binding classes for your layout file (you don’t want to use this feature), add the tools:viewBindingIgnore=”true” property to the root view of the layout file:
<LinearLayout
...
tools:viewBindingIgnore="true" >
...
</LinearLayout>
Copy the code
use
If view binding is enabled for a Module, a binding class is generated for each XML layout file that the Module contains. Each binding class contains a reference to the root view and all views that have ids. The name of the Binding class is generated by converting the name of the XML file to Pascal case and adding the word Binding at the end.
For example, given a layout file named activity_progressbar.xml:
<LinearLayout> ... <ProgressBar android:id="@+id/progress_1"/> <ProgressBar style="@android:style/Widget.ProgressBar.Small" /> <ProgressBar android:id="@+id/progress_3"/> <ProgressBar style="@android:style/Widget.ProgressBar.Inverse" /> <ProgressBar android:id="@+id/progress_5"/> <ProgressBar style="@android:style/Widget.ProgressBar.Large.Inverse" /> ... </LinearLayout>Copy the code
There are six Progressbars in the layout file, and only three progressbars have Android: ID set.
The generated binding class called ActivityProgressbarBinding. This class has three fields: PROGRESs_1, PROGRESs_3, and PROGRESs_5. The other three have no IDS in the layout, so are not mentioned in the binding class.
Each binding class also contains a getRoot() method that provides a direct reference to the root view of the corresponding layout file. In this case, the class of the getRoot ActivityProgressbarBinding () method returns the LinearLayout root view.
Use view bindings in your Activity
To set up an instance of the binding class for your Activity, do the following in the Activity’s onCreate() method:
- 1. Call the static method inflate() included in the generated binding class. This creates an instance of the binding class for the activity to be used.
- 2. Get a reference to the root view by calling getRoot().
- 3. Pass the root view to setContentView() to make it an active view on the screen.
Here’s an example:
private ActivityProgressbarBinding activityProgressbarBinding; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); activityProgressbarBinding = ActivityProgressbarBinding.inflate(getLayoutInflater()); // View view = activityProgressbarBinding.getRoot(); // setContentView(view); / / one pace reachs the designated position can also be the setContentView (activityProgressbarBinding getRoot ()); / / use the binding class instance to refer to any View (XML must add id) activityProgressbarBinding. Progress1. SetMax (120); activityProgressbarBinding.progress3.setProgress(20); }Copy the code
Use view binding in the Fragment
To set an instance of the bound class for use with the Fragment, perform the following steps in the onCreateView() method of the Fragment:
- 1. Call the static method inflate() included in the generated binding class. This creates an instance of the binding class for the Fragment to be used.
- 2. Get a reference to the root view by calling getRoot().
- 3. Return the root view from the onCreateView() method and make it the active view on the screen.
Note: The inflate() method requires you to pass in the layout inflator. If the layout is already your vehicle, you can call the static bind() method of your vehicle binding class instead.
Here’s an example:
private FragmentMineBinding binding;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentMineBinding.inflate(inflater,container,false);
View view = binding.getRoot();
return view;
}
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
Copy the code
Provides hints for different configurations
When you declare views across multiple configurations, sometimes it makes sense to use different view types based on a particular layout. Such as:
# in res/layout/example.xml
<TextView android:id="@+id/user_bio" />
# in res/layout-land/example.xml
<EditText android:id="@+id/user_bio" />
Copy the code
In this case, you might want the generated class to expose a userBio Type field TextView, because TextView is a public base class. Unfortunately, due to technical limitations, the View binding code generator is unable to make this decision and the View simply generates a field instead. This will require using binding.userBio as TextView later.
To address this limitation, view binding supports a Tools property :viewBindingType, which allows you to tell the compiler what type to use in generated code. In the example above, you can use this property to make the compiler generate a TextView for the field:
# in res/layout/example.xml (unchanged)
<TextView android:id="@+id/user_bio" />
# in res/layout-land/example.xml
<EditText android:id="@+id/user_bio" tools:viewBindingType="TextView" />
Copy the code
In another example, suppose you have two layouts, one containing the BottomationView and the other containing the NavigationRailView. Both NavigationBarView classes contain most of the implementation details. If your code doesn’t need to know exactly which subclass exists in the current layout, you can use Tools :viewBindingType to set the generated type to NavigationBarView in both layouts:
# in res/layout/navigation_example.xml
<BottomNavigationView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />
# in res/layout-w720/navigation_example.xml
<NavigationRailView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />
Copy the code
Note: View bindings cannot verify the value of this property when generating code. To avoid compile-time and run-time errors, the value must meet the following conditions:
- This value must be a class inherited from android.view.view.
- The value must be the superclass of the label on which it is placed. For example, the following values will not work:
<! -- ImageView is not related to TextView --> <TextView tools:viewBindingType="ImageView" /> <! -- Button is not a superclass of TextView --> <TextView tools:viewBindingType="Button" />Copy the code
- The final type must be resolved consistently across all configurations.
Difference from findViewById
View Binding has important advantages over using findViewById:
- Air safety: Because view binding creates a direct reference to the view, there is no risk of a null pointer exception due to an invalid view ID. In addition, when the view exists only in certain configurations of the layout, the fields in the binding class that contain its references are marked as @Nullable.
- Type safety: The types of fields in each binding class match the views referenced in the XML file. This means there is no risk of class cast exceptions.
These differences mean that incompatibilities between your layout and your code will cause your build to fail at compile time rather than run time.
Comparison with data binding
Both the View Binding and the Data Binding generate binding classes that can be used to refer directly to the View. However, the View Binding is intended to handle simpler use cases and provides the following advantages over the Data Binding:
- Faster compilation:View binding does not require annotation processing, so compile time is faster.
- Ease of use:View binding does not require a specially tagged XML layout file, so it is faster to adopt in your application. When view binding is enabled in a module, it is automatically applied to all layouts for that module.
In contrast, view binding has the following limitations compared to data binding:
- View binding is not supportedLayout variables or layout expressions, so it cannot be used to declare dynamic UI content directly from an XML layout file.
Layout variables or layout expressions: The expression language allows you to write expressions that handle events scheduled by a view. The data binding library automatically generates the classes needed to bind views in the layout to data objects.
- View binding does not support bidirectional data binding.
Bidirectional data binding: Unidirectional data binding, where you can set a value on a property and set a listener to react to the property changes. Bidirectional data binding provides a shortcut to this process.
Because of these considerations, in some cases it may be best to use both a View Binding and a Data Binding in your project. You can use a Data Binding for layouts that require advanced functionality and a View Binding for layouts that do not.
Note: In many cases, view binding can provide the same benefits as data binding, but with simpler implementation and better performance. If you’re primarily replacing the findViewById() call with data binding, it’s better to use view binding.
So that’s all about View Binding, so hopefully that helped you. We’ll look at Data Binding later when we have conditions.