1. Introduction This article introduces how to use the Data Binding library to write declarative layout files and bind your app logic and layout files with minimal code. The Data Binding library is not only flexible but also widely compatible - it is a support library, so you can use it on all Android platforms up to Android 2.1 (API level 7+). Requires: Android Studio 1.3.0-beta1 or higher. Test version Please note: Data Binding library is currently in beta. While Data Binding is in beta, developers should be aware of the following considerations: This is a beta version of a feature intended to generate developer feedback. It may contain bugs, or not be suitable for your use case, so use it at your own risk. That said, we'd love to get your feedback! Use the issue tracker to let us know what does or doesn't work for your use case. Beta versions of the Data Binding library are subject to significant changes, including those that are not source code compatible with your application. That is, significant rework may be required to update this library in the future. Developers can release apps built with beta versions of the Data Binding library at any time, although the standard Android SDK and Google Play Terms of Service caveats apply. And it’s always a good idea to thoroughly test your apps when adopting a new library or tool. We are just getting started with Android Studio support at this time. There will be further Android Studio support in the future. By using the Data Binding library beta version, you acknowledge these warnings. 2. Build environment To start using Data Binding, you first need to download the library from the Support Library in the Android SDK Manager. Please make sure you are using a compatible version of Android Studio. The Data Binding plugin for Android Studio requires Android Studio 1.3.0-beta1 or higher. Work Environment To use Data Binding in your app, you need to add Data Binding to the gradle build file, as follows:
Then make sure jcenter is in the repositories list, as follows:
In each module you want to use Data Binding, add the following plugin: apply plugin: 'com.android.application' apply plugin: 'com.android.databinding' The Data Binding plugin will add required and compile configuration dependencies to your project. 3. Data Binding Layout File Data Binding Expressions The Data Binding layout file is a little different: the starting root tag is layout, followed by a data element and a view root element. The view element is the root element of your layout file that does not use Data Binding. An example is as follows:
A variable attribute named user is described in data, making it available in this layout: <variable name="user" type="com.example.User"/> In the layout attribute expression, write @{}. Here is a TextView whose text is set to the user's firstName attribute:
Data Object Assume you have a plain-old Java Object (POJO) named user:
This type of object holds data that never changes. It is common in apps that can be read once and never changed afterwards. Of course, you can also use JavaBeans objects:
From a Data Binding perspective, these two classes are equivalent. The expression @{user.firstName} for the android:text attribute in TextView will access the firstName in the former POJO object and the getFirstName() method in the latter JavaBeans object. Binding Data By default, a Binding class is generated based on the name of the layout file, converting it to Pascal case and adding the "Binding" suffix. The layout file above is activity_main.xml, so the generated class name is ActivityMainBinding. This class contains all the bindings from layout properties to the layout's Views (such as the user variable), and it also knows how to assign values to Binding expressions. The simplest way to create bindings is during inflating as follows:
#p# 4. Dive into the Layout file Import Zero or more import elements may be used within a data element. These are used only to add references to your layout files, just like in Java:
Now, the View can use your Binding expression:
When there is a conflict in class names, one of the class names can be renamed to an alias:
Thus, in the layout file, Vista corresponds to com.example.real.estate.View, and View corresponds to android.view.View. The imported types can be used as references in variables and expressions:
Note: Android Studio does not yet handle imports, so automatic variable imports will not work in your IDE. Your app will still compile fine, and you can use fully qualified names in your variable definitions to work around the IDE issue.
Imported types can also use static properties and methods in expressions:
Just like in Java, java.lang.* is imported automatically. Variables Any number of variable elements can be used in data. Each variable element describes a property used in a Binding expression in a layout file.
The Variable type is checked at compile time, so if a Variable implements Observable or an observable collection, this should be reflected in the type. (Annotation: Need to find information to understand) If the variable is a basic class or interface that does not implement the Observable interface, Variables will not be observed! When there are different layout files for multiple configurations (e.g. landscape or portrait), the variables are merged. There must not be conflicting variable definitions between these layout files. The generated Binding class will have setters and getters for each of the described Variables. These Variables will use the default Java value - null (reference type), 0 (int), false (boolean), etc., until the setter is called. Custom Binding Class Name By default, the Binding class is named based on the layout file name, starting with uppercase, removing underscores () and the first letter after () and then adding the "Binding" suffix. This class will be placed in a databinding package in a module package. For example, the layout file contact_item.xml will generate ContactItemBinding. If the module package is com.example.my.app, then it will be placed in com.example.my.app.databinding. The Binding class can be renamed or placed in a different package by adjusting the class attribute in the data element. For example:
A Binding class named ContactItem will be generated in the databinding package of the module package. If you want to generate this class in a different package, you need to add the prefix ., as follows:
In this case, the ContactItem class is generated directly in the module package. Or you can provide the entire package name:
Includes Variables can be passed from a container layout to a contained layout by using the application namespace and the variable name in the attributes:
Note: User variables are required in both name.xml and contact.xml layout files. expression Common expressions are very similar to Java expressions. The following are the same: Math + - / * % String concatenation+ Logical && || Binary & | ^ Unary operations + - ! ~ Shift>> >>> << Comparison == > < >= <= instanceof Group() null Cast Method Call Data Access[] Ternary operation?: Example:
Missing operations : this super #p# Explicit generic calls Null Merge Operation ?? - the object on the left. If it is not null, select the object on the left; or if it is null, select the object on the right: android:text="@{user.displayName ?? user.lastName}" The function is written as follows:
Property reference The first one has been mentioned before: a) Data Binding expression: a short format of JavaBean reference. When an expression refers to a property of a class, it still uses the same format for fields, getters, and ObservableFields.
Data Binding code generation automatically checks for nulls to avoid null pointer exceptions. For example, in the expression @{user.name}, if user is null, user.name will be assigned its default value (null). If you reference user.age, age is an int type, then its default value is 0. gather Commonly used collections: arrays, lists, sparse lists, and maps, can all be accessed using [] for simplicity.
String When single quotes are used to enclose attribute values, it is easy to use double quotes in expressions:
It is also possible to use double quotes to enclose attribute values. The string must be enclosed in "`":
It is also possible to access resources using regular expressions: android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}" Format strings and pluralizations can be determined by providing parameters
When a complex number requires multiple arguments, all arguments are passed:
Some resources require explicit typing: Type Normal reference Expression reference
5. Data Object Any Plain old Java object (POJO) can be used for Data Binding, but modifying a POJO will not cause the UI to update. The real power of Data Binding is to notify your Data object when the data changes. There are three different data change notification mechanisms: Observable objects, ObservableFields, and observable collections. When these observable Data objects are bound to the UI, the UI will automatically update when the Data object properties change. Observable Object The class that implements the android.databinding.Observable interface allows you to attach a listener to a Bound object in order to monitor changes to all properties on the object. The Observable interface has a mechanism to add and remove listeners, but notifications are managed by the developer. To make development easier, a BaseObservable base class was created to implement the listener registration mechanism. The Data implementation class is still responsible for notifying when properties change. This is done by specifying a Bindable annotation to the getter and notifying in the setter.
During compilation, the Bindable annotation generates an Entry in the BR class file. The BR class file is generated in the module package. If the base class used for the Data class cannot be changed, the Observable interface is implemented through a convenient PropertyChangeRegistry for storage and efficient notification of listeners. Observable Fields Little work is involved in creating the Observable class, so developers who want to save time or have few properties can use ObservableFields. ObservableFields are self-contained observable objects with a single field. It has all primitive types and one reference type. To use it, create a public final field in the data object:
That's it, to access the value, use the set and get methods: user.firstName.set("Google"); int age = user.age.get(); Observable Collections Some apps use more dynamic structures to store data. Observable collections allow keyed access to these data objects. ObservableArrayMap is used when the keys are reference types, such as String.
In the layout file, the map can be accessed through the String key:
In the layout file, the list can be accessed by index:
The generated Binding class links the variables in the layout with the Views. As discussed earlier, the name and package name of the Binding can be customized. The generated Binding class extends android.databinding.ViewDataBinding. #p# create Bindings should be created right after inflation to ensure that the View hierarchy does not interfere with the previous expressions in the layout that bind to the views. There are several ways to bind to a layout. The most common is to use the static .inflate method on the Binding class to load the View hierarchy and bind to it. There is also a simpler version that only requires LayoutInflater and another one that uses ViewGroup: MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater); MyLayoutBinding binding = MyLayoutBinding.inflate(LayoutInflater, viewGroup, false); If a different mechanism is used to load the layout, it can be bound separately: MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot); Sometimes the Binding cannot be known in advance. In this case, you can use the DataBindingUtil class to create the Binding:
Views with IDs For each View with an ID in the layout, a public final field is generated. Binding makes a single pass over the View hierarchy, extracting the Views with IDs. This mechanism is faster than using findViewById for some Views. For example:
It will generate the following Binding class: public final TextView firstName; public final TextView lastName; IDs are not nearly as necessary as they would be without Data Bindings, but there will still be instances where you will need to access Views from your code. Variables Each Variable will have access methods.
It will generate setters and getters in Binding:
ViewStubs ViewStubs are slightly different from normal Views. They start out invisible, and when they are either made visible or explicitly told to load, they replace themselves by loading another layout. Since the ViewStub essentially disappears from the View hierarchy, the View in the Binding object must also disappear to allow it to be collected. Since Views are private, a ViewStubProxy object takes a ViewStub, giving the developer access to the ViewStub when it exists and also access to the loaded View hierarchy when the ViewStub is loaded. When another layout is loaded, a Binding must be created for the new layout. Therefore, the ViewStubProxy must listen to the ViewStub's OnInflateListener listener and create the Binding at that time. Since only one can exist, the ViewStubProxy allows developers to set an OnInflateListener on it which will be called after the Binding is created. Advanced Binding Dynamic Variables Sometimes, the specific Binding class is not known, for example, a RecyclerView adapter does arbitrary operations on layouts and does not know the specific Binding class. It still has to be assigned to the Binding during onBindViewHolder. In this example, all layouts bound to the RecyclerView have an "item" Variable. The BindingHolder has a getBinding method that returns a ViewDataBinding.
Direct Binding When a variable or observable changes, the binding is scheduled to change before the next frame. There are many times, but it must be executed immediately when binding. To force execution, use the executePendingBindings() method. Background Threads You can change your data model in a background thread as long as it is not a collection. Data Binding will localize each variable/field when deciding whether to avoid any concurrency issues. 7. Property Setters Whenever the binding value changes, the generated Binding class must call the setter method. The Data Binding framework has methods that can be used to customize the assignment. Automatic Setters For an attribute, Data Binding tries to find the setAttribute method. It has nothing to do with the namespace of the attribute, but only with the name of the attribute itself. For example, an expression for the android:text attribute of a TextView will look for a setText(String) method. If the expression returns an int, Data Binding will search for a setText(int) method. Note: To make the expression return the correct type, use casting if necessary. Data Binding will still work even if no attribute with the given name exists. You can then easily "invent" attributes for any setter through Data Binding. For example, DrawerLayout does not have any attributes, but a large number of setters. You can use one of them using automatic setters.
Renamed Setters Some properties that have setters do not match by name. For these methods, the property can be associated via the BindingMethods annotation. This must be associated with a class containing a BindingMethod annotation, one for each renamed method. For example, the android:tint attribute is associated with setImageTintList, not setTint.
In the above example, it is unlikely that the developer will need to rename the setters, as this is already implemented by the Android architecture attributes. Custom Setters Some properties require custom binding logic. For example, there is no setter for the android:paddingLeft property. Instead, setPadding(left, top, right, bottom) exists. A static binding adapter method annotated with BindingAdapter allows developers to customize how the setter is called for a property. Android has created BindingAdapters with properties. For example, for paddingLeft:
Binding adapters are useful for other custom types. For example, a custom loader can be used to load images asynchronously. When there is a conflict, the Binding adapter created by the developer will override the Data Binding default adapter. You can also create adapters that can receive multiple parameters.
This adapter is called if both imageUrl and error are used for an ImageView and imageUrl is a string and error is a drawable. Custom namespaces will be ignored during the matching process. You can also write adapters for Android namespaces. #p# 8. Conversion Object conversion When returning an object from a Binding expression, a setter is selected from automatic, renamed, and custom setters. The object is converted to the parameter type of the selected setter. This is for convenience of those using ObservableMaps to store data. For example:
In userMap an object is returned and the object will be automatically converted to the parameter type of setText(CharSequence). When there may be confusion about the parameter type, the developer needs to convert in the expression. Custom Transformations Sometimes conversions should be automatic between certain types. For example, when setting a background:
Here, the background requires a Drawable object, but the color is an integer. Whenever there is a Drawable and the return value is an integer, the integer type is converted to a ColorDrawable. This conversion is done by using a static method annotated with BindingConversion:
Note: Conversion only happens at the setter level, so it is not allowed to mix the following types:
|
<<: How to become a top coder in three years
>>: 10 design principles that developers should know
Review expert: Shen Yingjian, Director of the Nut...
With the advent of the 5G era, mobile Internet is...
Every winter, we always see a lot of news about p...
Is it necessary to make every penny of advertisin...
Recently, a magical operation of "absorbing ...
1 second, 2 seconds, 3 seconds... Several "c...
People of different eras created big brands that ...
The most important thing about an event is to hav...
This article mainly introduces what to do if the ...
Douyinmen·2022 Doudian no-source store group, the...
As China's national-level APP, there are not ...
This task is usually led by the product director ...
Mysterious and profound, the door to all wonders....
Have you watched the popular ancient puppet drama...
How much does it cost to be an agent of Qiandongn...