From 1c964bece6ce1bbbf9f641d95df3bf2de01f6ab7 Mon Sep 17 00:00:00 2001 From: George Mount Date: Mon, 27 Jul 2015 10:38:22 -0700 Subject: Revert "am 6397ae6a: Merge "Update data binding for RC1." into mnc-preview-docs" This reverts commit c571a9a1d026cbf262cf36a5348f99d1ca0ec835, reversing changes made to a29cfefe2c157a28b256771b1dce4653d405dcf1. This should fix the build break for LMP downstream branches. Change-Id: I22aac1dd0fb7965a2877bae224bccc8df8ee8e17 --- docs/html/tools/data-binding/guide.jd | 732 +++++++++++++--------------------- 1 file changed, 270 insertions(+), 462 deletions(-) diff --git a/docs/html/tools/data-binding/guide.jd b/docs/html/tools/data-binding/guide.jd index 2de5bc2..7c4c15a 100644 --- a/docs/html/tools/data-binding/guide.jd +++ b/docs/html/tools/data-binding/guide.jd @@ -28,10 +28,6 @@ page.tags="databinding", "layouts"
  • Binding Data
  • - -
  • - Binding Events -
  • @@ -145,7 +141,7 @@ page.tags="databinding", "layouts" — it's a support library, so you can use it with all Android platform versions back to Android 2.1 (API level 7+).

    -

    To use data binding, Android Plugin for Gradle 1.3.0-beta4 +

    To use data binding, Android Plugin for Gradle 1.3.0-beta1 or higher is required.

    Beta release

    @@ -191,9 +187,9 @@ or higher is required.

    To get started with Data Binding, download the library from the Support repository in the Android SDK manager.

    -

    The Data Binding plugin requires Android Plugin for Gradle 1.3.0-beta4 -or higher, so update your build dependencies (in the top-level -build.gradle file) as needed.

    +

    The Data Binding plugin requires Android Plugin for Gradle 1.3.0-beta1 +or higher, so update your build dependencies (in +build.gradle) as needed.

    Also, make sure you are using a compatible version of Android Studio. Android Studio 1.3 adds the code-completion and layout-preview @@ -205,18 +201,18 @@ support for data binding.

    To set up your application to use data binding, add data binding to the class - path of your top-level build.gradle file, right below "android". + path of your build.gradle file, right below "android".

        dependencies {
    -       classpath "com.android.tools.build:gradle:1.3.0-beta4"
    -       classpath "com.android.databinding:dataBinder:1.0-rc1"
    +       classpath "com.android.tools.build:gradle:1.3.0-beta1"
    +       classpath "com.android.databinding:dataBinder:1.0-rc0"
        }
    +}
     

    - Then make sure jcenter is in the repositories list for your projects in the top-level - build.gradle file. + Then make sure jcenter is in the repositories list for your sub projects.

    @@ -232,8 +228,8 @@ allprojects {
     

    -apply plugin: 'com.android.application'
    -apply plugin: 'com.android.databinding'
    +apply plugin: ‘com.android.application'
    +apply plugin: 'com.android.databinding'
     

    The data binding plugin is going to add necessary provided @@ -256,23 +252,23 @@ apply plugin: 'com.android.databinding'

    -<?xml version="1.0" encoding="utf-8"?>
    -<layout xmlns:android="http://schemas.android.com/apk/res/android">
    -   <data>
    -       <variable name="user" type="com.example.User"/>
    -   </data>
    -   <LinearLayout
    +<?xml version="1.0" encoding="utf-8"?>
    +<layout xmlns:android="http://schemas.android.com/apk/res/android">
    +   <data>
    +       <variable name="user" type="com.example.User"/>
    +   </data>
    +   <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
    -       android:layout_height="match_parent">
    -       <TextView android:layout_width="wrap_content"
    +       android:layout_height="match_parent">
    +       <TextView android:layout_width="wrap_content"
                android:layout_height="wrap_content"
    -           android:text="@{user.firstName}"/>
    -       <TextView android:layout_width="wrap_content"
    +           android:text="@{user.firstName}"/>
    +       <TextView android:layout_width="wrap_content"
                android:layout_height="wrap_content"
    -           android:text="@{user.lastName}"/>
    -   </LinearLayout>
    -</layout>
    +           android:text="@{user.lastName}"/>
    +   </LinearLayout>
    +</layout>
     

    The user variable within data describes a @@ -289,9 +285,9 @@ apply plugin: 'com.android.databinding'

    -<TextView android:layout_width="wrap_content"
    +<TextView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
    -          android:text="@{user.firstName}"/>
    +          android:text="@{user.firstName}"/>
     

    Data Object @@ -302,12 +298,12 @@ apply plugin: 'com.android.databinding'

    -public class User {
    -   public final String firstName;
    -   public final String lastName;
    -   public User(String firstName, String lastName) {
    -       this.firstName = firstName;
    -       this.lastName = lastName;
    +public class User {
    +   public final String firstName;
    +   public final String lastName;
    +   public User(String firstName, String lastName) {
    +       this.firstName = firstName;
    +       this.lastName = lastName;
        }
     }
     
    @@ -318,18 +314,18 @@ public class User {

    -public class User {
    -   private final String firstName;
    -   private final String lastName;
    -   public User(String firstName, String lastName) {
    -       this.firstName = firstName;
    -       this.lastName = lastName;
    +public class User {
    +   private final String firstName;
    +   private final String lastName;
    +   public User(String firstName, String lastName) {
    +       this.firstName = firstName;
    +       this.lastName = lastName;
        }
    -   public String getFirstName() {
    -       return this.firstName;
    +   public String getFirstName() {
    +       return this.firstName;
        }
    -   public String getLastName() {
    -       return this.lastName;
    +   public String getLastName() {
    +       return this.lastName;
        }
     }
     
    @@ -338,8 +334,7 @@ public class User { expression @{user.firstName} used for the TextView’s android:text attribute will access the firstName field in the former class - and the getFirstName() method in the latter class. Alternatively, it - will also be resolved to firstName() if that method exists. + and the getFirstName() method in the latter class.

    @@ -349,8 +344,8 @@ public class User {

    By default, a Binding class will be generated based on the name of the layout file, converting it to Pascal case and suffixing “Binding” to it. The above - layout file was main_activity.xml so the generate class was - MainActivityBinding. This class holds all the bindings from the + layout file was activity_main.xml so the generate class was + ActivityMainBinding. This class holds all the bindings from the layout properties (e.g. the user variable) to the layout’s Views and knows how to assign values for the binding expressions.The easiest means for creating the bindings is to do it while inflating: @@ -358,10 +353,10 @@ public class User {

     @Override
    -protected void onCreate(Bundle savedInstanceState) {
    -   super.onCreate(savedInstanceState);
    -   MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
    -   User user = new User("Test", "User");
    +protected void onCreate(Bundle savedInstanceState) {
    +   super.onCreate(savedInstanceState);
    +   ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
    +   User user = new User("Test", "User");
        binding.setUser(user);
     }
     
    @@ -379,55 +374,11 @@ MainActivityBinding binding = MainActivityBinding.inflate(getLayoutInfl

    -ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
    +ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup,
    +false);
     //or
     ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
     
    - -

    - Binding Events -

    -

    - Events may be bound to handler methods directly, similar to the way - android:onClick can be assigned to a method in the Activity. - Event attribute names are governed by the name of the listener method with a few exceptions. - For example, {@link android.view.View.OnLongClickListener} has a method {@link android.view.View.OnLongClickListener#onLongClick onLongClick()}, - so the attribute for this event is android:onLongClick. -

    -

    - To assign an event to its handler, use a normal binding expression, with the value - being the method name to call. For example, if your data object has two methods: -

    -
    public class MyHandlers {
    -    public void onClickFriend(View view) { ... }
    -    public void onClickEnemy(View view) { ... }
    -}
    -
    -

    - The binding expression can assign the click listener for a View: -

    -
    -<?xml version="1.0" encoding="utf-8"?>
    -<layout xmlns:android="http://schemas.android.com/apk/res/android">
    -   <data>
    -       <variable name="handlers" type="com.example.Handlers"/>
    -       <variable name="user" type="com.example.User"/>
    -   </data>
    -   <LinearLayout
    -       android:orientation="vertical"
    -       android:layout_width="match_parent"
    -       android:layout_height="match_parent">
    -       <TextView android:layout_width="wrap_content"
    -           android:layout_height="wrap_content"
    -           android:text="@{user.firstName}"
    -           android:onClick="@{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/>
    -       <TextView android:layout_width="wrap_content"
    -           android:layout_height="wrap_content"
    -           android:text="@{user.lastName}"
    -           android:onClick="@{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/>
    -   </LinearLayout>
    -</layout>
    -

    Layout Details

    @@ -443,20 +394,20 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay

    -<data>
    -    <import type="android.view.View"/>
    -</data>
    +<data>
    +    <import type="android.view.View"/>
    +</data>
     

    Now, View may be used within your binding expression:

    -<TextView
    +<TextView
        android:text="@{user.lastName}"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
    -   android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>
    +   android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>
     

    When there are class name conflicts, one of the classes may be renamed to an @@ -464,9 +415,9 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay

    -<import type="android.view.View"/>
    -<import type="com.example.real.estate.View"
    -        alias="Vista"/>
    +<import type="android.view.View"/>
    +<import type="com.example.real.estate.View"
    +        alias="Vista"/>
     

    Now, Vista may be used to reference the @@ -477,12 +428,12 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay

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

    Note: Android Studio does not yet handle imports so the @@ -492,10 +443,10 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay

    -<TextView
    +<TextView
        android:text="@{((User)(user.connection)).lastName}"
        android:layout_width="wrap_content"
    -   android:layout_height="wrap_content"/>
    +   android:layout_height="wrap_content"/>
     

    Imported types may also be used when referencing static fields and methods in @@ -503,15 +454,15 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay

    -<data>
    -    <import type="com.example.MyStringUtils"/>
    -    <variable name="user" type="com.example.User"/>
    -</data>
    +<data>
    +    <import type="com.example.MyStringUtils"/>
    +    <variable name="user" type="com.example.User"/>
    +</data>
     …
    -<TextView
    +<TextView
        android:text="@{MyStringUtils.capitalize(user.lastName)}"
        android:layout_width="wrap_content"
    -   android:layout_height="wrap_content"/>
    +   android:layout_height="wrap_content"/>
     

    Just as in Java, java.lang.* is imported automatically. @@ -530,16 +481,16 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay

    -<data>
    -    <import type="android.graphics.drawable.Drawable"/>
    -    <variable name="user"  type="com.example.User"/>
    -    <variable name="image" type="Drawable"/>
    -    <variable name="note"  type="String"/>
    -</data>
    +<data>
    +    <import type="android.graphics.drawable.Drawable"/>
    +    <variable name="user"  type="com.example.User"/>
    +    <variable name="image" type="Drawable"/>
    +    <variable name="note"  type="String"/>
    +</data>
     

    The variable types are inspected at compile time, so if a variable implements - {@link android.databinding.Observable} or is an Observable or is an observable collection, that should be reflected in the type. If the variable is a base class or interface that does not implement the Observable* interface, the variables will not @@ -582,9 +533,9 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay

    -<data class="ContactItem">
    +<data class="ContactItem">
         ...
    -</data>
    +</data>
     

    This generates the binding class as ContactItem in the @@ -594,9 +545,9 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay

    -<data class=".ContactItem">
    +<data class=".ContactItem">
         ...
    -</data>
    +</data>
     

    In this case, ContactItem is generated in the module package @@ -604,9 +555,9 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay

    -<data class="com.example.ContactItem">
    +<data class="com.example.ContactItem">
         ...
    -</data>
    +</data>
     

    Includes @@ -619,46 +570,28 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay

    -<?xml version="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="user" type="com.example.User"/>
    -   </data>
    -   <LinearLayout
    +<?xml version="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="user" type="com.example.User"/>
    +   </data>
    +   <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
    -       android:layout_height="match_parent">
    -       <include layout="@layout/name"
    -           bind:user="@{user}"/>
    -       <include layout="@layout/contact"
    -           bind:user="@{user}"/>
    -   </LinearLayout>
    -</layout>
    +       android:layout_height="match_parent">
    +       <include layout="@layout/name"
    +           bind:user="@{user}"/>
    +       <include layout="@layout/contact"
    +           bind:user="@{user}"/>
    +   </LinearLayout>
    +</layout>
     

    Here, there must be a user variable in both the name.xml and contact.xml layout files.

    -

    - Data binding does not support include as a direct child of a merge element. For example, - the following layout is not supported: -

    -
    -<?xml version="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="user" type="com.example.User"/>
    -   </data>
    -   <merge>
    -       <include layout="@layout/name"
    -           bind:user="@{user}"/>
    -       <include layout="@layout/contact"
    -           bind:user="@{user}"/>
    -   </merge>
    -</layout>
    -
    +

    Expression Language

    @@ -680,10 +613,10 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay
  • - Logical && || + Logical && ||
  • -
  • Binary & | ^ +
  • Binary & | ^
  • Unary + - ! ~ @@ -726,9 +659,9 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay

    -android:text="@{String.valueOf(index + 1)}"
    +android:text="@{String.valueOf(index + 1)}"
     android:visibility="@{age &lt; 13 ? View.GONE : View.VISIBLE}"
    -android:transitionName='@{"image_" + id}'
    +android:transitionName='@{"image_" + id}'
     

    Missing Operations @@ -813,23 +746,23 @@ android:transitionName='@{"image_" + id}'

    -<data>
    -    <import type="android.util.SparseArray"/>
    -    <import type="java.util.Map"/>
    -    <import type="java.util.List"/>
    -    <variable name="list" type="List&lt;String>"/>
    -    <variable name="sparse" type="SparseArray&lt;String>"/>
    -    <variable name="map" type="Map&lt;String, String>"/>
    -    <variable name="index" type="int"/>
    -    <variable name="key" type="String"/>
    -</data>
    -…
    -android:text="@{list[index]}"
    +<data>
    +    <import type="android.util.SparseArray"/>
    +    <import type="java.util.Map"/>
    +    <import type="java.util.List"/>
    +    <variable name="list" type="List<String>"/>
    +    <variable name="sparse" type="SparseArray&lt;String>"/>
    +    <variable name="map" type="Map&lt;String, String>"/>
    +    <variable name="index" type="int"/>
    +    <variable name="key" type="String"/>
    +</data>
     …
    -android:text="@{sparse[index]}"
    -…
    -android:text="@{map[key]}"
    -
    +android:text="@{list[index]}"
    +…
    +android:text="@{sparse[index]}"
    +…
    +android:text="@{map[key]}"
    +
     

    String Literals @@ -841,7 +774,7 @@ android:text="@{map[key]}"

    -android:text='@{map["firstName"]}'
    +android:text='@{map["firstName"]}'
     

    It is also possible to use double quotes to surround the attribute value. @@ -850,8 +783,8 @@ android:text='@{map["firstName"]}'

    -android:text="@{map[`firstName`}"
    -android:text="@{map[&quot;firstName&quot;]}"
    +android:text="@{map[`firstName`}"
    +android:text="@{map[&quot;firstName&quot;]}"
     

    Resources @@ -863,15 +796,15 @@ android:text="@{map[&quot;firstName&quot;]}"

    -android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"
    +android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"
     

    Format strings and plurals may be evaluated by providing parameters:

    -android:text="@{@string/nameFormat(firstName, lastName)}"
    -android:text="@{@plurals/banana(bananaCount)}"
    +android:text="@{@string/nameFormat(firstName, lastName)}"
    +android:text="@{@plurals/banana(bananaCount)}"
     

    When a plural takes multiple parameters, all parameters should be passed: @@ -882,7 +815,7 @@ android:text="@{@plurals/banana(bananaCount)}" Have an orange Have %d oranges -android:text="@{@plurals/orange(orangeCount, orangeCount)}" +android:text="@{@plurals/orange(orangeCount, orangeCount)}"

  • Some resources require explicit type evaluation. @@ -903,7 +836,9 @@ android:text="@{@plurals/orange(orangeCount, orangeCount)}" - String[] +

    +String[]
    +
    @array @@ -966,7 +901,9 @@ android:text="@{@plurals/orange(orangeCount, orangeCount)}" color int - @color +
    +@color
    +
    @color @@ -995,9 +932,8 @@ android:text="@{@plurals/orange(orangeCount, orangeCount)}" a POJO will not cause the UI to update. The real power of data binding can be used by giving your data objects the ability to notify when data changes. There are three different data change notification mechanisms, - Observable objects, - observable fields, and - observable collections. + Observable objects, ObservableFields, and + observable collections.

    @@ -1010,49 +946,49 @@ android:text="@{@plurals/orange(orangeCount, orangeCount)}"

    - A class implementing the {@link android.databinding.Observable} interface + A class implementing android.databinding.Observable interface will allow the binding to attach a single listener to a bound object to listen for changes of all properties on that object.

    - The {@link android.databinding.Observable} interface has a mechanism to add and remove + The Observable interface has a mechanism to add and remove listeners, but notifying is up to the developer. To make development easier, - a base class, {@link android.databinding.BaseObservable}, was created to implement the + a base class, BaseObservable, was created to implement the listener registration mechanism. The data class implementer is still responsible for notifying when the properties change. This is done by - assigning a {@link android.databinding.Bindable} annotation to the getter and notifying in + assigning a Bindable annotation to the getter and notifying in the setter.

    -private static class User extends BaseObservable {
    -   private String firstName;
    -   private String lastName;
    +private static class User extends BaseObservable {
    +   private String firstName;
    +   private String lastName;
        @Bindable
    -   public String getFirstName() {
    -       return this.firstName;
    +   public String getFirstName() {
    +       return this.firstName;
        }
        @Bindable
    -   public String getLastName() {
    -       return this.lastName;
    +   public String getFirstName() {
    +       return this.lastName;
        }
    -   public void setFirstName(String firstName) {
    -       this.firstName = firstName;
    +   public void setFirstName(String firstName) {
    +       this.firstName = firstName;
            notifyPropertyChanged(BR.firstName);
        }
    -   public void setLastName(String lastName) {
    -       this.lastName = lastName;
    +   public void setLastName(String lastName) {
    +       this.lastName = lastName;
            notifyPropertyChanged(BR.lastName);
        }
     }
     

    - The {@link android.databinding.Bindable} annotation generates an entry in the BR class file + The Bindable annotation generates an entry in the BR class file during compilation. The BR class file will be generated in the module - package. If the base class for data classes cannot be changed, the - {@link android.databinding.Observable} interface may be implemented using the convenient - {@link android.databinding.PropertyChangeRegistry} to store and notify listeners + package.If the base class for data classes cannot be changed, the + Observable interface may be implemented using the convenient + PropertyChangeRegistry to store and notify listeners efficiently.

    @@ -1061,30 +997,20 @@ private static class User extends BaseObservable {

    - A little work is involved in creating {@link android.databinding.Observable} classes, so - developers who want to save time or have few properties may use - {@link android.databinding.ObservableField} and its siblings - {@link android.databinding.ObservableBoolean}, - {@link android.databinding.ObservableByte}, - {@link android.databinding.ObservableChar}, - {@link android.databinding.ObservableShort}, - {@link android.databinding.ObservableInt}, - {@link android.databinding.ObservableLong}, - {@link android.databinding.ObservableFloat}, - {@link android.databinding.ObservableDouble}, and - {@link android.databinding.ObservableParcelable}. - ObservableFields are self-contained observable objects that have a single - field. The primitive versions avoid boxing and unboxing during access operations. - To use, create a public final field in the data class: + A little work is involved in creating Observable classes, so developers who + want to save time or have few properties may use ObservableFields. + ObservableFields are self-contained observable objects that have a single + field. There are versions for all primitive types and one for reference + types. To use, create a public final field in the data class:

    -private static class User {
    -   public final ObservableField<String> firstName =
    -       new ObservableField<>();
    -   public final ObservableField<String> lastName =
    -       new ObservableField<>();
    -   public final ObservableInt age = new ObservableInt();
    +private static class User extends BaseObservable {
    +   public final ObservableField<String> firstName =
    +       new ObservableField<>();
    +   public final ObservableField<String> lastName =
    +       new ObservableField<>();
    +   public final ObservableInt age = new ObservableInt();
     }
     

    @@ -1092,8 +1018,8 @@ private static class User {

    -user.firstName.set("Google");
    -int age = user.age.get();
    +user.firstName.set("Google");
    +int age = user.age.get();
     

    Observable Collections @@ -1101,44 +1027,43 @@ int age = user.age.get();

    Some applications use more dynamic structures to hold data. Observable - collections allow keyed access to these data objects. - {@link android.databinding.ObservableArrayMap} is + collections allow keyed access to these data objects.ObservableArrayMap is useful when the key is a reference type, such as String.

    -ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();
    -user.put("firstName", "Google");
    -user.put("lastName", "Inc.");
    -user.put("age", 17);
    +ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();
    +user.put("firstName", "Google");
    +user.put("lastName", "Inc.");
    +user.put("age", 17);
     

    In the layout, the map may be accessed through the String keys:

    -<data>
    -    <import type="android.databinding.ObservableMap"/>
    -    <variable name="user" type="ObservableMap&lt;String, Object>"/>
    -</data>
    +<data>
    +    <import type="android.databinding.ObservableMap"/>
    +    <variable name="user" type="ObservableMap&lt;String, Object>"/>
    +</data>
     …
    -<TextView
    +<TextView
        android:text='@{user["lastName"]}'
        android:layout_width="wrap_content"
    -   android:layout_height="wrap_content"/>
    -<TextView
    +   android:layout_height="wrap_content"/>
    +<TextView
        android:text='@{String.valueOf(1 + (Integer)user["age"])}'
        android:layout_width="wrap_content"
    -   android:layout_height="wrap_content"/>
    +   android:layout_height="wrap_content"/>
     

    - {@link android.databinding.ObservableArrayList} is useful when the key is an integer: + ObservableArrayList is useful when the key is an integer:

    -ObservableArrayList<Object> user = new ObservableArrayList<>();
    -user.add("Google");
    -user.add("Inc.");
    +ObservableArrayList<Object> user = new ObservableArrayList<>();
    +user.add("Google");
    +user.add("Inc.");
     user.add(17);
     

    @@ -1146,20 +1071,20 @@ user.add(17);

    -<data>
    -    <import type="android.databinding.ObservableList"/>
    -    <import type="com.example.my.app.Fields"/>
    -    <variable name="user" type="ObservableList&lt;Object>"/>
    -</data>
    +<data>
    +    <import type="android.databinding.ObservableList"/>
    +    <import type="com.example.my.app.Fields"/>
    +    <variable name="user" type="ObservableList&lt;Object>"/>
    +</data>
     …
    -<TextView
    +<TextView
        android:text='@{user[Fields.LAST_NAME]}'
        android:layout_width="wrap_content"
    -   android:layout_height="wrap_content"/>
    -<TextView
    +   android:layout_height="wrap_content"/>
    +<TextView
        android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}'
        android:layout_width="wrap_content"
    -   android:layout_height="wrap_content"/>
    +   android:layout_height="wrap_content"/>
     

    Generated Binding @@ -1169,7 +1094,7 @@ user.add(17); The generated binding class links the layout variables with the Views within the layout. As discussed earlier, the name and package of the Binding may be customized. The Generated binding - classes all extend {@link android.databinding.ViewDataBinding}. + classes all extend android.databinding.ViewDataBinding.

    @@ -1182,13 +1107,13 @@ user.add(17); within the layout. There are a few ways to bind to a layout. The most common is to use the static methods on the Binding class.The inflate method inflates the View hierarchy and binds to it all it one step. There is a simpler - version that only takes a {@link android.view.LayoutInflater} and one that takes a - {@link android.view.ViewGroup} as well: + version that only takes a LayoutInflater and one that takes a + ViewGroup as well:

    -MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater);
    -MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false);
    +MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater);
    +MyLayoutBinding binding = MyLayoutBinding.inflate(LayoutInflater, viewGroup, false);
     

    If the layout was inflated using a different mechanism, it may be bound @@ -1196,17 +1121,17 @@ MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, fal

    -MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);
    +MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);
     

    Sometimes the binding cannot be known in advance. In such cases, the binding - can be created using the {@link android.databinding.DataBindingUtil} class: + can be created using the DataBindingUtil class:

    -ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId,
    +ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId,
         parent, attachToParent);
    -ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);
    +ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);
     

    Views With IDs @@ -1220,32 +1145,32 @@ ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);

    -<layout xmlns:android="http://schemas.android.com/apk/res/android">
    -   <data>
    -       <variable name="user" type="com.example.User"/>
    -   </data>
    -   <LinearLayout
    +<layout xmlns:android="http://schemas.android.com/apk/res/android">
    +   <data>
    +       <variable name="user" type="com.example.User"/>
    +   </data>
    +   <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
    -       android:layout_height="match_parent">
    -       <TextView android:layout_width="wrap_content"
    +       android:layout_height="match_parent">
    +       <TextView android:layout_width="wrap_content"
                android:layout_height="wrap_content"
    -           android:text="@{user.firstName}"
    -   android:id="@+id/firstName"/>
    -       <TextView android:layout_width="wrap_content"
    +           android:text="@{user.firstName}"
    +   android:id="@+id/firstName"/>
    +       <TextView android:layout_width="wrap_content"
                android:layout_height="wrap_content"
    -           android:text="@{user.lastName}"
    -  android:id="@+id/lastName"/>
    -   </LinearLayout>
    -</layout>
    +           android:text="@{user.lastName}"
    +  android:id="@+id/lastName"/>
    +   </LinearLayout>
    +</layout>
     

    Will generate a binding class with:

    -public final TextView firstName;
    -public final TextView lastName;
    +public final TextView firstName;
    +public final TextView lastName;
     

    IDs are not nearly as necessary as without data binding, but there are still @@ -1261,49 +1186,49 @@ public final TextView lastName;

    -<data>
    -    <import type="android.graphics.drawable.Drawable"/>
    -    <variable name="user"  type="com.example.User"/>
    -    <variable name="image" type="Drawable"/>
    -    <variable name="note"  type="String"/>
    -</data>
    +<data>
    +    <import type="android.graphics.drawable.Drawable"/>
    +    <variable name="user"  type="com.example.User"/>
    +    <variable name="image" type="Drawable"/>
    +    <variable name="note"  type="String"/>
    +</data>
     

    will generate setters and getters in the binding:

    -public abstract com.example.User getUser();
    -public abstract void setUser(com.example.User user);
    -public abstract Drawable getImage();
    -public abstract void setImage(Drawable image);
    -public abstract String getNote();
    -public abstract void setNote(String note);
    +public abstract com.example.User getUser();
    +public abstract void setUser(com.example.User user);
    +public abstract Drawable getImage();
    +public abstract void setImage(Drawable image);
    +public abstract String getNote();
    +public abstract void setNote(String note);
     

    ViewStubs

    - {@link android.view.ViewStub}s are a little different from normal Views. They start off invisible + ViewStubs are a little different from normal Views. They start off invisible and when they either are made visible or are explicitly told to inflate, they replace themselves in the layout by inflating another layout.

    - Because the ViewStub essentially disappears from the View hierarchy, the View + Because the ViewStub essentially disappears from the View hierarchy, the View in the binding object must also disappear to allow collection. Because the - Views are final, a {@link android.databinding.ViewStubProxy} object takes the place of the - ViewStub, giving the developer access to the ViewStub when it exists and also - access to the inflated View hierarchy when the ViewStub has been inflated. + Views are final, a ViewStubProxy object takes the place of the ViewStub, + giving the developer access to the ViewStub when it exists and also access to + the inflated View hierarchy when the ViewStub has been inflated.

    When inflating another layout, a binding must be established for the new - layout. Therefore, the ViewStubProxy must listen to the ViewStub's - {@link android.view.ViewStub.OnInflateListener} and establish the binding at that time. Since - only one can exist, the ViewStubProxy allows the developer to set an - OnInflateListener on it that it will call after establishing the binding. + layout. Therefore, the ViewStubProxy must listen to the ViewStub's + OnInflateListener and establish the binding at that time. Since only one can + exist, the ViewStubProxy allows the developer to set an OnInflateListener on + it that it will call after establishing the binding.

    @@ -1316,20 +1241,20 @@ public abstract void setNote(String note);

    At times, the specific binding class won't be known. For example, a - {@link android.support.v7.widget.RecyclerView.Adapter} operating against arbitrary layouts - won't know the specific binding class. It still must assign the binding value during the - {@link android.support.v7.widget.RecyclerView.Adapter#onBindViewHolder}. + RecyclerView Adapter operating against arbitrary layouts won't know the + specific binding class. It still must assign the binding value during the + onBindViewHolder.

    In this example, all layouts that the RecyclerView binds to have an "item" - variable. The BindingHolder has a getBinding method returning the - {@link android.databinding.ViewDataBinding} base. + variable. The BindingHolder has a getBinding method returning the + ViewDataBinding base.

    -public void onBindViewHolder(BindingHolder holder, int position) {
    -   final T item = mItems.get(position);
    +public void onBindViewHolder(BindingHolder holder, int position) {
    +   final T item = mItems.get(position);
        holder.getBinding().setVariable(BR.item, item);
        holder.getBinding().executePendingBindings();
     }
    @@ -1342,7 +1267,7 @@ public void onBindViewHolder(BindingHolder holder, int position) {
       When a variable or observable changes, the binding will be scheduled to
       change before the next frame. There are times, however, when binding must be
       executed immediately. To force execution, use the
    -  {@link android.databinding.ViewDataBinding#executePendingBindings()} method.
    +  executePendingBindings() method.
     

    @@ -1396,18 +1321,17 @@ namespace for the attribute does not matter, only the attribute name itself.

    Some attributes have setters that don't match by name. For these methods, an attribute may be associated with the setter through - {@link android.databinding.BindingMethods} annotation. This must be associated with - a class and contains {@link android.databinding.BindingMethod} annotations, one for - each renamed method. For example, the android:tint attribute - is really associated with {@link android.widget.ImageView#setImageTintList}, not - setTint. + BindingMethods annotation. This must be associated with a class and contains + BindingMethod annotations, one for each renamed method. For example, the + android:tint attribute is really associated + with setImageTintList, not setTint.

     @BindingMethods({
    -       @BindingMethod(type = "android.widget.ImageView",
    -                      attribute = "android:tint",
    -                      method = "setImageTintList"),
    +       @BindingMethod(type = "android.widget.ImageView",
    +                      attribute = "android:tint",
    +                      method = "setImageTintList"),
     })
     

    @@ -1423,7 +1347,7 @@ namespace for the attribute does not matter, only the attribute name itself. Some attributes need custom binding logic. For example, there is no associated setter for the android:paddingLeft attribute. Instead, setPadding(left, top, right, bottom) exists. - A static binding adapter method with the {@link android.databinding.BindingAdapter} + A static binding adapter method with the BindingAdapter annotation allows the developer to customize how a setter for an attribute is called.

    @@ -1434,8 +1358,9 @@ namespace for the attribute does not matter, only the attribute name itself.

    -@BindingAdapter("android:paddingLeft")
    -public static void setPaddingLeft(View view, int padding) {
    +
    +@BindingAdapter("android:paddingLeft")
    +public static void setPaddingLeft(View view, int padding) {
        view.setPadding(padding,
                        view.getPaddingTop(),
                        view.getPaddingRight(),
    @@ -1457,9 +1382,9 @@ public static void setPaddingLeft(View view, int padding) {
     

    -@BindingAdapter({"bind:imageUrl", "bind:error"})
    -public static void loadImage(ImageView view, String url, Drawable error) {
    -   Picasso.with(view.getContext()).load(url).error(error).into(view);
    +@BindingAdapter({"bind:imageUrl", "bind:error"})
    +public static void loadImage(ImageView view, String url, Drawable error) {
    +   Picasso.with(view.getContext()).load(url).error(error).into(view);
     }
     
    @@ -1481,123 +1406,6 @@ app:error=“@{@drawable/venueError}”/>
       
     
     
    -

    - Binding adapter methods may optionally take the old values in their handlers. A method - taking old and new values should have all old values for the attributes come first, followed - by the new values: -

    -
    -@BindingAdapter("android:paddingLeft")
    -public static void setPaddingLeft(View view, int oldPadding, int newPadding) {
    -   if (oldPadding != newPadding) {
    -       view.setPadding(newPadding,
    -                       view.getPaddingTop(),
    -                       view.getPaddingRight(),
    -                       view.getPaddingBottom());
    -   }
    -}
    -
    -

    - Event handlers may only be used with interfaces or abstract classes with one abstract method. - For example: -

    -
    -@BindingAdapter("android:onLayoutChange")
    -public static void setOnLayoutChangeListener(View view, View.OnLayoutChangeListener oldValue,
    -       View.OnLayoutChangeListener newValue) {
    -    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    -        if (oldValue != null) {
    -            view.removeOnLayoutChangeListener(oldValue);
    -        }
    -        if (newValue != null) {
    -            view.addOnLayoutChangeListener(newValue);
    -        }
    -    }
    -}
    -
    -

    - When a listener has multiple methods, it must be split into multiple listeners. For example, - {@link android.view.View.OnAttachStateChangeListener} has two methods: - {@link android.view.View.OnAttachStateChangeListener#onViewAttachedToWindow onViewAttachedToWindow()} and - {@link android.view.View.OnAttachStateChangeListener#onViewDetachedFromWindow onViewDetachedFromWindow()}. - We must then create two interfaces to differentiate the attributes and handlers for them. -

    - -
    -@TargetApi(VERSION_CODES.HONEYCOMB_MR1)
    -public interface OnViewDetachedFromWindow {
    -    void onViewDetachedFromWindow(View v);
    -}
    -
    -@TargetApi(VERSION_CODES.HONEYCOMB_MR1)
    -public interface OnViewAttachedToWindow {
    -    void onViewAttachedToWindow(View v);
    -}
    -
    -

    - Because changing one listener will also affect the other, we must have three different - binding adapters, one for each attribute and one for both, should they both be set. -

    -
    -@BindingAdapter("android:onViewAttachedToWindow")
    -public static void setListener(View view, OnViewAttachedToWindow attached) {
    -    setListener(view, null, attached);
    -}
    -
    -@BindingAdapter("android:onViewDetachedFromWindow")
    -public static void setListener(View view, OnViewDetachedFromWindow detached) {
    -    setListener(view, detached, null);
    -}
    -
    -@BindingAdapter({"android:onViewDetachedFromWindow", "android:onViewAttachedToWindow"})
    -public static void setListener(View view, final OnViewDetachedFromWindow detach,
    -        final OnViewAttachedToWindow attach) {
    -    if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) {
    -        final OnAttachStateChangeListener newListener;
    -        if (detach == null && attach == null) {
    -            newListener = null;
    -        } else {
    -            newListener = new OnAttachStateChangeListener() {
    -                @Override
    -                public void onViewAttachedToWindow(View v) {
    -                    if (attach != null) {
    -                        attach.onViewAttachedToWindow(v);
    -                    }
    -                }
    -
    -                @Override
    -                public void onViewDetachedFromWindow(View v) {
    -                    if (detach != null) {
    -                        detach.onViewDetachedFromWindow(v);
    -                    }
    -                }
    -            };
    -        }
    -        final OnAttachStateChangeListener oldListener = ListenerUtil.trackListener(view,
    -                newListener, R.id.onAttachStateChangeListener);
    -        if (oldListener != null) {
    -            view.removeOnAttachStateChangeListener(oldListener);
    -        }
    -        if (newListener != null) {
    -            view.addOnAttachStateChangeListener(newListener);
    -        }
    -    }
    -}
    -
    -

    - The above example is slightly more complicated than normal because View uses add and remove - for the listener instead of a set method for {@link android.view.View.OnAttachStateChangeListener}. - The android.databinding.adapters.ListenerUtil class helps keep track of the previous - listeners so that they may be removed in the Binding Adaper. -

    -

    - By annotating the interfaces OnViewDetachedFromWindow and - OnViewAttachedToWindow with - @TargetApi(VERSION_CODES.HONEYCOMB_MR1), the data binding code - generator knows that the listener should only be generated when running on Honeycomb MR1 - and new devices, the same version supported by - {@link android.view.View#addOnAttachStateChangeListener}. -

    Converters

    @@ -1618,10 +1426,10 @@ public static void setListener(View view, final OnViewDetachedFromWindow detach,

    -<TextView
    +<TextView
        android:text='@{userMap["lastName"]}'
        android:layout_width="wrap_content"
    -   android:layout_height="wrap_content"/>
    +   android:layout_height="wrap_content"/>
     

    @@ -1639,10 +1447,10 @@ The userMap returns an Object and that Object will be automatically

    -<View
    +<View
        android:background="@{isError ? @color/red : @color/white}"
        android:layout_width="wrap_content"
    -   android:layout_height="wrap_content"/>
    +   android:layout_height="wrap_content"/>
     

    Here, the background takes a Drawable, but the color is an @@ -1654,8 +1462,8 @@ The userMap returns an Object and that Object will be automatically

     @BindingConversion
    -public static ColorDrawable convertColorToDrawable(int color) {
    -   return new ColorDrawable(color);
    +public static ColorDrawable convertColorToDrawable(int color) {
    +   return new ColorDrawable(color);
     }
     

    @@ -1664,8 +1472,8 @@ public static ColorDrawable convertColorToDrawable(int color) {

    -<View
    +<View
        android:background="@{isError ? @drawable/error : @color/white}"
        android:layout_width="wrap_content"
    -   android:layout_height="wrap_content"/>
    +   android:layout_height="wrap_content"/>
     
    -- cgit v1.1