Data binding is a process that establishes a connection between an application's UI and its business logic so that when data changes, it is reflected in the UI and vice versa. Android introduced data binding in 2015 to minimize glue code between layouts and logic. The key steps to using data binding are: 1) adding the data binding library, 2) applying binding to layouts, 3) creating data binding objects, and 4) doing the binding in activities/fragments. Data binding supports observable objects to automatically update views when data changes. It allows binding layout properties like visibility and text fields.
20 yrs tinkeringwith computers
A lot of time on software localization
On Android since 2010 (Cupcake)
Mobile R+D Lead at Worldine Iberia
Android GDE (Google Developer Expert)
I love making UI
Proud parent of a 8 years old OS fan
@sergiandreplace
sergiandreplace.com
sergi.Martinez[at]gmail.com
About me – Sergi Martínez
3.
Android data binding
Introducedby Google in I/O 2015 (almost unnoticed)
But really important. It will change the way we make UIs
4.
Google dixit
Writing declarativelayouts and minimize the
glue code necessary to bind your application
logic and layouts.
Data Binding library is for...
5.
What is databinding?
Data binding is the process that establishes a
connection between the application UI (User
Interface) and Business logic. If the settings and
notifications are correctly set, the data reflects
changes when made. It can also mean that when
the UI is changed, the underlying data will reflect
that change
Wikipedia – Data binding
z
Inflation process
Inflate as
Oralso performed inside setContentView
LayoutInflater.from(this).inflate(R.layout.activity_main, rootView);
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
9.
Steps on inflation
1.The inflater parses the xml file
2. The inflater tries to create an object as:
a. android.widget.<tag>
b. android.webkit.<tag>
c. <tag>
3. If succeds: creates the objects and sets the right
properties
If fails: hell on earth
10.
z
Some code (usingcustom inflater)
New inflater defined as InflaterFactory
11.
z
Some code (usingcustom inflater)
New inflater defined as InflaterFactory
12.
z
Some code (usingcustom inflater)
Once we set a new InflatorFactory, we are ready for inflation
The whole example
Checkit out on
https://github.com/sergiandreplace/AndroidFontInflaterFactory
(old Eclipse structure)
Also an experiment, use at your own risk
z
Apply binding tolayout
New root tag <layout>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="data"
type="com.sergiandreplace.hellodatabinding.ViewData" />
</data>
<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=“@{data.helloMessage}" />
</RelativeLayout>
</layout>
29.
z
Apply binding tolayout
Two parts: data and layout itself
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="data"
type="com.sergiandreplace.hellodatabinding.ViewData" />
</data>
<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=“@{data.helloMessage}" />
</RelativeLayout>
</layout>
30.
z
Apply binding tolayout
Name of object to be injected and type of the object
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="data"
type="com.sergiandreplace.hellodatabinding.ViewData" />
</data>
<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=“@{data.helloMessage}" />
</RelativeLayout>
</layout>
31.
z
Apply binding tolayout
Binded property of the object
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="data"
type="com.sergiandreplace.hellodatabinding.ViewData" />
</data>
<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=“@{data.helloMessage}" />
</RelativeLayout>
</layout>
32.
z
Create data bindingobject
This way:
Or this way:
public class ViewData {
public final String helloMessage;
public ViewData(String helloMessage) {
this.helloMessage = helloMessage;
}
}
public class ViewData {
private final String helloMessage;
public ViewData(String helloMessage) {
this.helloMessage = helloMessage;
}
public String getHelloMessage() {
return helloMessage;
}
}
33.
z
Create data bindingobject
This way:
Or this way:
public class ViewData {
public final String helloMessage;
public ViewData(String helloMessage) {
this.helloMessage = helloMessage;
}
}
public class ViewData {
private final String helloMessage;
public ViewData(String helloMessage) {
this.helloMessage = helloMessage;
}
public String getHelloMessage() {
return helloMessage;
}
}
34.
z
Create data bindingobject
This way:
Or this way:
public class ViewData {
public final String helloMessage;
public ViewData(String helloMessage) {
this.helloMessage = helloMessage;
}
}
public class ViewData {
private final String helloMessage;
public ViewData(String helloMessage) {
this.helloMessage = helloMessage;
}
public String getHelloMessage() {
return helloMessage;
}
}
35.
z
Do the binding
Onthe activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
ViewData data = new ViewData(getString(R.string.hello_world));
binding.setData(data);
}
36.
z
Do the binding
Onthe activity
We create the binding object
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
ViewData data = new ViewData(getString(R.string.hello_world));
binding.setData(data);
}
37.
z
Do the binding
Onthe activity
Layout name Proper cased + Binding (activity_main.xml -> ActivityMainBinding)
Generated on compilation. You must launch make before AS can recognize
Only worked with canary (1.4 RC3)
1.4 published yesterday (it should work)
You must use Java 1.7 as language level
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
ViewData data = new ViewData(getString(R.string.hello_world));
binding.setData(data);
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
38.
z
Do the binding
Onthe activity
Instantiate our ViewData object and set a message
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
ViewData data = new ViewData(getString(R.string.hello_world));
binding.setData(data);
}
39.
z
Do the binding
Onthe activity
Give the data object to the binding for the painting
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
ViewData data = new ViewData(getString(R.string.hello_world));
binding.setData(data);
}
z
Other things todo
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_offer”
android:visibility="@{product.isOffer? View.VISIBLE : View.GONE}"/>
<data>
<import type="android.view.View"/>
<variable name=“product” type=“com.sergiandreplace.hellodatabinding.product”/>
</data>
42.
z
More things todo
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{StringUtils.getFormatCurrency(product.price, product.currency)}”
/>
<data>
<import type="com.sergiandreplace.hellodatabinding.StringUtils"/>
<variable name=“product” type=“com.sergiandreplace.hellodatabinding.product”/>
</data>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{StringUtils.getFormatCurrency(product.Price) + product.currency}”
/>
43.
z
Include with Binding
<?xmlversion="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<data>
<variable name=“product" type=“com.sergiandreplace.hellodatabinding.Product"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/header"
bind:product="@{product}"/>
<include layout="@layout/detail"
bind:product="@{product}"/>
</LinearLayout>
</layout>
Merge not supported
z
Observable objects
Extends BaseObservable
privatestatic class Product extends BaseObservable {
private String name;
private String description;
@Bindable
public String getName() {
return this.name;
}
@Bindable
public String getDescription() {
return this.description;
}
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
public void setLastName(String description) {
this. description = description;
notifyPropertyChanged(BR. description);
}
}
48.
z
Observable objects
Declare gettersas bindable
private static class Product extends BaseObservable {
private String name;
private String description;
@Bindable
public String getName() {
return this.name;
}
@Bindable
public String getDescription() {
return this.description;
}
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
public void setLastName(String description) {
this. description = description;
notifyPropertyChanged(BR. description);
}
}
49.
z
Observable objects
Notify changes
BRis like R for Bindables (aka: magic generated on compilation)
private static class Product extends BaseObservable {
private String name;
private String description;
@Bindable
public String getName() {
return this.name;
}
@Bindable
public String getDescription() {
return this.description;
}
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
public void setLastName(String description) {
this. description = description;
notifyPropertyChanged(BR.description);
}
}
50.
z
Even easier: observablefields
private static class Product{
public final ObservableField<String> name =
new ObservableField<>();
public final ObservableField<String> description =
new ObservableField<>();
public final ObservableInt stock = new ObservableInt();
}
51.
z
Even easier: observablefields
ObservableField just uses generics for any class
private static class Product{
public final ObservableField<String> name =
new ObservableField<>();
public final ObservableField<String> description =
new ObservableField<>();
public final ObservableInt stock = new ObservableInt();
}
52.
z
Even easier: observablefields
ObservableInt, ObservableLong, ObservableParcelable, etc, already usable
private static class Product{
public final ObservableField<String> name =
new ObservableField<>();
public final ObservableField<String> description =
new ObservableField<>();
public final ObservableInt stock = new ObservableInt();
}
53.
z
Even easier: observablefields
To use them…
private static class Product{
public final ObservableField<String> name =
new ObservableField<>();
public final ObservableField<String> description =
new ObservableField<>();
public final ObservableInt stock = new ObservableInt();
}
Product.stock.get();
product.name.set(“Biscuits”);
54.
Attribute setters
Binding librarytries to match the attribute setter with
attribute name
Ex: on android:text=“@{…}” it looks for the setText method
In some cases we want something more accurated
We can create our own attribute setters
Final big advice
Donot put business logic in the View Model
CLEARLY separate business-logic and representation-logic
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/discount”
android:visibility="@{product.isOffer? 0.15 : 0}"/>
62.
Final big advice
Donot put business logic in the View Model
CLEARLY separate business-logic and representation-logic
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/discount”
android:visibility="@{product.isOffer? 0.15 : 0}"/>
20 yrs tinkeringwith computers
A lot of time on software localization
On Android since 2010 (Cupcake)
Mobile R+D Lead at Worldine Iberia
Android GDE (Google Developer
Expert)
I love making UI
Proud parent of a 8 years old OS fan
@sergiandreplace
sergiandreplace.com
sergi.Martinez[at]gmail.com
About me – Sergi Martínez