Android Databinding

Denis Kniazhev

About me

Java EE - 8 years

Android - 2 years

Did some Java desktop, Javascript, PHP, Databases, iOS along the way

 

Currently Development Manager of Mobile project (iOS and Android)

 

github.com/denisk20

Databinding connects UI and Data Models

What's Databinding?

View

Model

Template

One-Way Binding

Compiles

Template

Model

View

Model is the single source of truth

Compiles

Two-Way Binding

JSP

?

Databinding in Android

  • Introduced in Android Marshmallow
  • Was initially planned for Lollipop, but Lollipop became too huge
  • First prototype was built in late 2014
  • Version RC-0 has been presented at Google I/O 2015
  • Is a Support Library - works on API 7+
<LinearLayout …>
    <TextView android:id="@+id/name"/>
    <TextView android:id="@+id/lastName"/>
</LinearLayout>
private TextView name
private TextView lastName;

protected void onCreate(Bundle savedInstanceState) {
  setContentView(R.layout.activity_main);

  name = (TextView) findViewById(R.id.name);
  lastName = (TextView) findViewById(R.id.lastName);
}

public void updateUI(User user) {
  if (user == null) {
    name.setText(null);
    lastName.setText(null);
  } else {
    name.setText(user.getName());
    lastName.setText(user.getLastName());
  }

findViewById

null check

name and lastName need to be set separately

Motivation

@Bind(R.id.name) TextView name
@Bind(R.id.lastName) TextView lastName;

protected void onCreate(Bundle savedInstanceState) {
  setContentView(R.layout.activity_main);
  ButterKnife.bind(this);
}

public void updateUI(User user) {
  if (user == null) {
    name.setText(null);
    lastName.setText(null);
  } else {
    name.setText(user.getName());
    lastName.setText(user.getLastName());
  }
}

Libraries like Butterknife can improve it

Databinding

<layout>
    <data>
        <variable name="user"
                  type="com.android.example.User"/>
    </data>
    <LinearLayout …>
        <TextView android:text="@{user.name}"/>
        <TextView android:text="@{user.lastName}"/>
    </LinearLayout>
</layout>
private ActivityMainBinding binding;

protected void onCreate(Bundle savedInstanceState) {
  binding = DataBindingUtil.setContentView(
    this, R.layout.activity_main);
}

public void updateUI(User user) {
  binding.setUser(user);
}

activity_main.xml:

Expression language

Generated class

Call this instead of activity.setContentView

Declare variable

Databinding Expression language

mostly Java

  • Mathematical + - / * %
  • String concatenation +
  • Logical && ||
  • Binary & | ^
  • Unary + - ! ~
  • Shift >> >>> <<
  • Comparison == > < >= <=
  • instanceof
  • Grouping ()
  • Literals - character, String, numeric, null
  • Cast
  • Method calls
  • Field access
  • Array access []
  • Ternary operator ?:

Missing operators:  this, super, new

Resources:

<TextView android:text='@{user.isMale ? @string/male : @string/female}' />
<data>
    <import type="android.view.View"/>
</data>
...
<TextView android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}" .../>

Imports:

Variables:

<data>
    <import type="com.example.User"/>
    <import type="java.util.List"/>
    <variable name="user" type="User"/>
    <variable name="userList" type="List&lt;User>"/>
</data>

No NullPointerException

{
  "user": {
    "name": "John"
  }
}
if(response != null && response.user != null) {
    nameView.setText(response.user.name);
}
android:text="@{response.user.name}"

Extra functionality

Null coalescing

textView.setText(user.name != null 
              ? user.name : "unknown");
android:text='@{user.name ?? "unknown"}'

becomes

becomes

Observable Objects

public class User extends BaseObservable {
   private String firstName;

   @Bindable
   public String getFirstName() {
       return this.firstName;
   }

   public void setFirstName(String firstName) {
       this.firstName = firstName;
       notifyPropertyChanged(BR.firstName);
   }
}
<TextView android:text="@{user.firstName}" />

extend BaseObservable or implement Observable

Annotate fields with @Bindable

Notify of field change

Observable fields

public class User {
   public final ObservableField<String> firstName =
       new ObservableField<>();
   public final ObservableInt age = new ObservableInt();
}

user.firstName.set("John");
int age = user.age.get();
<TextView android:text="@{user.firstName}" />
<TextView android:text="@{user.age}" />

ObservableFields are implemented for all primitives and for Objects

call get and set

reference the fields in XML

How to set it up?

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.1'
        classpath 'com.android.databinding:dataBinder:1.0-rc4'
    }
}
<LinearLayout …>
    <TextView .../>
    <TextView .../>
</LinearLayout>

activity_main.xml:

<layout>
    <data>
        ...
    </data>
    <LinearLayout …>
        <TextView .../>
        <TextView .../>
    </LinearLayout>
</layout>

MainActivity.java:

ActivityMainBinding binding = 
  DataBindingUtil.setContentView(
    this, R.layout.activity_main);
setContentViev(R.layout.activity_main);

becomes

becomes

How it works?

All code generation and expression parsing happens at compile time => if an expression has error the project won't compile

No reflection, no runtime overhead

Performance

The compiler needs to traverse the views once - no findViewById needed

textView = (TextView) findViewById(R.id.myTextView);
textView = binding.myTextView;

Expressions are cached

<TextView android:text='@{"Hello " + user.isMale ? @string/male : @string/female}' />
<TextView android:text='@{"Goodbye " + user.isMale ? @string/male : @string/female}' />

UI updates are batched together.

Bindings can be updated on ANY thread.

becomes

Databinding Summary

  • Eliminates SO MUCH boilerplate
  • Is in support library
  • Compile-time validation
  • Performance is fantastic
  • Don't need to update views on UI thread
  • Models are the Single Source Of Truth

+

-

  • IDE integration
  • IDE integration
  • IDE integration

Links

Yigit Boyar and George Mount: Databinding talk

https://realm.io/news/data-binding-android-boyar-mount/

Android Developer Backstage podcast: Databinding

http://androidbackstage.blogspot.com/2015/09/episode-35-data-bound.html

Droidcon NYC 2015 - Data Binding Techniques

https://www.youtube.com/watch?v=WdUbXWztKNY

Thank you!

Questions?

Made with Slides.com