From 05eaab6a1eb21240fc66b8b114e92a83839ab4f5 Mon Sep 17 00:00:00 2001 From: Yigit Boyar Date: Wed, 25 May 2016 10:45:01 -0700 Subject: Docs: Completed updates to the Data Binding docs Bug: 28987432 Change-Id: I29d630618f9fff20e3c266f9b8ff59629fc607be --- docs/html/topic/libraries/data-binding/index.jd | 235 +++++++++++++++++++----- 1 file changed, 190 insertions(+), 45 deletions(-) diff --git a/docs/html/topic/libraries/data-binding/index.jd b/docs/html/topic/libraries/data-binding/index.jd index ca8784ebfcfb..293de51ea000 100644 --- a/docs/html/topic/libraries/data-binding/index.jd +++ b/docs/html/topic/libraries/data-binding/index.jd @@ -18,7 +18,7 @@ page.tags="databinding", "layouts" Data Binding Layout Files
  1. - Writing your first data binding + Writing your first set of data binding expressions
  2. @@ -29,9 +29,16 @@ page.tags="databinding", "layouts"
  3. Binding Data
  4. -
  5. - Binding Events + Event Handling +
      +
    1. + Method References +
    2. +
    3. + Listener Bindings +
    4. +
@@ -147,27 +154,34 @@ page.tags="databinding", "layouts" application logic and layouts.

-

The Data Binding Library offers both flexibility and broad compatibility -— it's a support library, so you can use it with all Android platform -versions back to Android 2.1 (API level 7+).

+

+ The Data Binding Library offers both flexibility and broad compatibility — + 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.5.0-alpha1 -or higher is required.

+

+ To use data binding, Android Plugin for Gradle 1.5.0-alpha1 + or higher is required. +

Build Environment

-

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

-

-To configure your app to use data binding, add the dataBinding element to your -build.gradle file in the app module. + To get started with Data Binding, download the library from the Support + repository in the Android SDK manager.

-

Use the following code snippet to configure data binding:

+

+ To configure your app to use data binding, add the dataBinding + element to your build.gradle file in the app module. +

+

+ Use the following code snippet to configure data binding: +

 android {
     ....
@@ -176,13 +190,17 @@ android {
     }
 }
 
+

+ If you have an app module that depends on a library which uses data binding, + your app module must configure data binding in its build.gradle + file as well. +

-

If you have an app module that depends on a library which uses data binding, your app module - must configure data binding in its build.gradle file as well.

- -

Also, make sure you are using a compatible version of Android Studio. -Android Studio 1.3 and later provides support for data binding as described in -Android Studio Support for Data Binding. +

+ Also, make sure you are using a compatible version of Android Studio. + Android Studio 1.3 and later provides support for data + binding as described in Android Studio Support for + Data Binding.

@@ -190,7 +208,7 @@ android {

- Writing your first data binding expressions + Writing your first set of data binding expressions

@@ -223,20 +241,19 @@ android { The user variable within data describes a property that may be used within this layout.

-
 <variable name="user" type="com.example.User"/>
 

Expressions within the layout are written in the attribute properties using - the “@{}” syntax. Here, the TextView’s text is set to the - firstName property of user: + the “&commat;{}” syntax. Here, the TextView’s text is set to + the firstName property of user:

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

Data Object @@ -261,7 +278,6 @@ public class User { to have data that is read once and never changes thereafter. It is also possible to use a JavaBeans objects:

-
 public class User {
    private final String firstName;
@@ -280,11 +296,12 @@ public class User {
 

From the perspective of data binding, these two classes are equivalent. The - expression @{user.firstName} used for - the TextView’s android:text attribute will + expression &commat;{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. + Alternatively, it will also be resolved to firstName() if that + method exists.

@@ -328,16 +345,38 @@ ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, fal //or ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false); - -

- Binding Events -

+

Event Handling

- 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. +Data Binding allows you to write expressions handling events that are dispatched from the views (e.g. onClick). +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. +There are two ways to handle an event. +

+ +

+ Method References +

+

+ Events can be bound to handler methods directly, similar to the way + android:onClick can be assigned to a method in an Activity. + One major advantage compared to the {@code View#onClick} attribute is that the expression + is processed at compile time, so if the method does not exist or its signature is not + correct, you receive a compile time error.

+

+ The major difference between Method References and Listener Bindings is that + the actual listener implementation is created when the data is bound, not + when the event is triggered. If you prefer to evaluate the expression when + the event happens, you should use listener + binding.

To assign an event to its handler, use a normal binding expression, with the value @@ -345,7 +384,6 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay

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

@@ -365,14 +403,121 @@ ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.lay <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}"/> + android:onClick="@{handlers::onClickFriend}"/> </LinearLayout> </layout> +

+Note that the signature of the method in the expression must exactly match the signature of the method in the +Listener object. +

+

+ Listener Bindings +

+

+ Listener Bindings are binding expressions that run when an event happens. + They are similar to method references, but they let you run arbitrary data + binding expressions. This feature is available with Android Gradle Plugin for Gradle + version 2.0 and later. +

+

+ In method references, the parameters of the method must + match the parameters of the event listener. In Listener Bindings, only your + return value must match the expected return value of the listener (unless it + is expecting void). + For example, you can have a presenter class that has the following method: +

+
+public class Presenter {
+    public void onSaveClick(Task task){}
+}
+
+ Then you can bind the click event to your class as follows: +
+  <?xml version="1.0" encoding="utf-8"?>
+  <layout xmlns:android="http://schemas.android.com/apk/res/android">
+      <data>
+          <variable name="task" type="com.android.example.Task" />
+          <variable name="presenter" type="com.android.example.Presenter" />
+      </data>
+      <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">
+          <Button android:layout_width="wrap_content" android:layout_height="wrap_content"
+          android:onClick="@{() -> presenter.onSaveClick(task)}" />
+      </LinearLayout>
+  </layout>
+
+

+ Listeners are represented by lambda expressions that are allowed only as root + elements of your expressions. When a callback is used in an expression, Data + Binding automatically creates the necessary listener and registers for the + event. When the view fires the event, Data Binding evaluates the given + expression. As in regular binding expressions, you still get the null and + thread safety of Data Binding while these listener expressions are being + evaluated. +

+

+ Note that in the example above, we haven't defined the {@code view} parameter + that is passed into {@link + android.view.View.OnClickListener#onClick(android.view.View view)}. Listener + bindings provide two choices for listener parameters: you can either ignore + all parameters to the method or name all of them. If you prefer to name the + parameters, you can use them in your expression. For example, the expression + above could be written as: +

+
+  android:onClick="@{(view) -> presenter.onSaveClick(task)}"
+
+Or if you wanted to use the parameter in the expression, it could work as follows: +
+public class Presenter {
+    public void onSaveClick(View view, Task task){}
+}
+
+
+  android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"
+
+You can use a lambda expression with more than one parameter: +
+public class Presenter {
+    public void onCompletedChanged(Task task, boolean completed){}
+}
+
+
+  <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content"
+        android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />
+
+

+ If the event you are listening to returns a value whose type is not {@code + void}, your expressions must return the same type of value as well. For + example, if you want to listen for the long click event, your expression + should return {@code boolean}. +

+
+public class Presenter {
+    public boolean onLongClick(View view, Task task){}
+}
+
+
+  android:onLongClick="@{(theView) -> presenter.onLongClick(theView, task)}"
+
+

+If the expression cannot be evaluated due to {@code null} objects, Data Binding returns +the default Java value for that type. For example, {@code null} for reference types, {@code 0} for {@code int}, +{@code false} for {@code boolean}, etc. +

+

+If you need to use an expression with a predicate (e.g. ternary), you can use +{@code void} as a symbol. +

+
+  android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}"
+
+ +
Avoid Complex Listeners
+Listener expressions are very powerful and can make your code very easy to read. +On the other hand, listeners containing complex expressions make your layouts hard to read and unmaintainable. +These expressions should be as simple as passing available data from your UI to your callback method. You should implement +any business logic inside the callback method that you invoked from the listener expression.

Some specialized click event handlers exist and they need an attribute other than -- cgit v1.2.3-59-g8ed1b