An essential part of developing Android apps involves the interaction between the code and the views that make up the user interface layouts. This chapter will look at the options available for gaining access to layout views in code, emphasizing an option known as view binding. Once the basics of view bindings have been covered, the chapter will outline how to convert the AndroidSample project to use this approach.
Find View by Id
As outlined in the chapter entitled Understanding Android App Structure, all of the resources that make up an application are compiled into a class named R. Amongst those resources are those that define layouts. Within the R class is a subclass named layout, which contains the layout resources, including the views that make up the user interface. Most apps will need to implement interaction between the code and these views, for example, when reading the value entered into the EditText view or changing the content displayed on a TextView.
Before the introduction of Android Studio 3.6, the most common option for gaining access to a view from within the app code involved writing code to manually find a view based on its id via the findViewById() method. For example:
TextView exampleView = findViewById(R.id.exampleView);
Code language: Java (java)
With the reference obtained, the view’s properties can then be accessed. For example:
exampleView.setText("Hello");
Code language: Java (java)
While finding views by id is still a viable option, it has some limitations, the most significant disadvantage of findViewById() being that it is possible to obtain a reference to a view that has not yet been created within the layout, leading to a null pointer exception when an attempt is made to access the view’s properties.
Since Android Studio 3.6, an alternative way of accessing views from the app code has been available in the form of view binding.
View Binding
When view binding is enabled in an app module, Android Studio automatically generates a binding class for each layout file. The layout views can be accessed from within the code using this binding class without using findViewById().
The name of the binding class generated by Android Studio is based on the layout file name converted to so-called “camel case” with the word “Binding” appended to the end. For the activity_main.xml file, for example, the binding class will be called ActivityMainBinding.
Android Studio Giraffe is inconsistent in using view bindings within project templates. For example, the Empty Views Activity template used when we created the AndroidSample project does not use view bindings. The Basic Views Activity template, on the other hand, is implemented using view binding. If you use a template that does not use view binding, it is important to know how to add it to your project.
Converting the AndroidSample project
In the remainder of this chapter, we will practice migrating to view bindings by converting the AndroidSample project to use view binding instead of findViewById().
Begin by launching Android Studio and opening the AndroidSample project created in the chapter entitled A Java Android Studio Example App.
Enabling View Binding
To use view binding, some changes must first be made to the build.gradle.kts file for each module in which view binding is needed. In the case of the AndroidSample project, this will require a slight change to the Gradle Scripts -> build.gradle.kts (Module: app) file. Load this file into the editor, locate the android section and add an entry to enable the viewBinding property as follows:
plugins {
id("com.android.application")
}
android {
buildFeatures {
viewBinding = true
}
.
.
Code language: Gradle (gradle)
Once this change has been made, click on the Sync Now link at the top of the editor panel, then use the Build menu to clean and rebuild the project to ensure the binding class is generated. The next step is to use the binding class within the code.
Using View Binding
The first step in this process is to “inflate” the view binding class to access the root view within the layout. This root view will then be used as the content view for the layout.
The logical place to perform these tasks is within the onCreate() method of the activity associated with the layout. A typical onCreate() method will read as follows:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
Code language: Java (java)
To switch to using view binding, the view binding class will need to be imported and the class modified as follows. Note that since the layout file is named activity_main.xml, we can surmise that the binding class generated by Android Studio will be named ActivityMainBinding. Note that if you used a domain other than com.example when creating the project, the import statement below would need to be changed to reflect this:
.
.
import android.widget.EditText;
import android.widget.TextView;
.
.
import com.example.androidsample.databinding.ActivityMainBinding;
.
.
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
.
.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
binding = ActivityMainBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
}
Code language: Java (java)
Now that we have a reference to the binding, we can access the views by name as follows:
public void convertCurrency(View view) {
// EditText dollarText = findViewById(R.id.dollarText);
// TextView textView = findViewById(R.id.textView);
if (!binding.dollarText.getText().toString().equals("")) {
Float dollarValue = Float.valueOf(
binding.dollarText.getText().toString());
Float euroValue = dollarValue * 0.85F;
binding.textView.setText(String.format(Locale.ENGLISH,"%.2f",
euroValue));
} else {
binding.textView.setText(R.string.no_value_string);
}
}
Code language: Java (java)
Compile and run the app and verify that the currency conversion process works as before.
Choosing an Option
Notwithstanding their failure to adopt view bindings in the Empty Views Activity project template, Google strongly recommends using view binding wherever possible. Therefore, view binding should be used when developing your own projects.
View Binding in the Book Examples
Any chapters in this book that rely on a project template that does not implement view binding will first be migrated. Instead of replicating the steps every time a migration needs to be performed, however, these chapters will refer you back here to refresh your memory (don’t worry, after a few chapters, the necessary changes will become second nature). To help with the process, the following section summarizes the migration steps more concisely.
Migrating a Project to View Binding
The process for converting a project module to use view binding involves the following steps:
1. Edit the module-level Gradle build script file listed in the Project tool window as Gradle Scripts -> build.gradle.kts (Module :app) where <project name> is the name of the project (for example AndroidSample).
2. Locate the android section of the file and add an entry to enable the viewBinding property as follows:
android {
buildFeatures {
viewBinding = true
}
.
.
Code language: Gradle (gradle)
3. Click on the Sync Now link at the top of the editor to resynchronize the project with these new build settings.
4. Edit the MainActivity.java file and modify it to read as follows (where <reverse domain> represents the domain name used when the project was created and <project name> is replaced by the lowercase name of the project, for example, androidsample) and <binding name> is the name of the binding for the corresponding layout resource file (for example, the binding for activity_main.xml is ActivityMainBinding).
.
.
import android.view.View;
import com.<reverse domain>.<project name>.databinding.<binding name>;
public class MainActivity extends AppCompatActivity {
private <binding name> binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
binding = <binding name>.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
}
Code language: Java (java)
5. Access views by name as properties of the binding object.
Summary
Before the introduction of Android Studio 3.6, access to layout views from within the code of an app involved using the findViewById() method. An alternative is now available in the form of view bindings. View bindings consist of classes Android Studio automatically generates for each XML layout file. These classes contain bindings to each view in the corresponding layout, providing a safer option than the findViewById() method. However, as of Android Studio Giraffe, view bindings are not enabled by default in some project templates. Additional steps are required to enable and configure support within each project module manually.