blob: ddcc9f2e7ea85ce5b9f88d0af0eb8091410439f3 [file] [log] [blame]
Andrew Solovay7877f692016-04-26 16:00:59 -07001page.title=Data Binding Library
2page.metaDescription=The Data Binding Library enables you to write declarative layouts.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07003page.tags="databinding", "layouts"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07004@jd:body
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07005
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07006<div id="qv-wrapper">
7 <div id="qv">
8 <h2>
9 In this document:
10 </h2>
11
12 <ol>
13 <li>
14 <a href="#build_environment">Build Environment</a>
15 </li>
16
17 <li>
18 <a href="#data_binding_layout_files">Data Binding Layout Files</a>
19 <ol>
20 <li>
Yigit Boyar05eaab62016-05-25 10:45:01 -070021 <a href="#writing_expressions">Writing your first set of data binding
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070022 expressions</a>
23 </li>
24
25 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070026 <a href="#data_object">Data Object</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070027 </li>
28
29 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070030 <a href="#binding_data">Binding Data</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070031 </li>
George Mount4ba18202015-07-27 12:39:28 -070032 <li>
Yigit Boyar05eaab62016-05-25 10:45:01 -070033 <a href="#event_handling">Event Handling</a>
34 <ol>
35 <li>
36 <a href="#method_references">Method References</a>
37 </li>
38 <li>
39 <a href="#listener_bindings">Listener Bindings</a>
40 </li>
41 </ol>
George Mount4ba18202015-07-27 12:39:28 -070042 </li>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070043 </ol>
44 </li>
45
46 <li>
47 <a href="#layout_details">Layout Details</a>
48 <ol>
49 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070050 <a href="#imports">Imports</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070051 </li>
52
53 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070054 <a href="#variables">Variables</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070055 </li>
56
57 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070058 <a href="#custom_binding_class_names">Custom Binding Class Names</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070059 </li>
60
61 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070062 <a href="#includes">Includes</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070063 </li>
64
65 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070066 <a href="#expression_language">Expression Language</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070067 </li>
68 </ol>
69 </li>
70
71 <li>
72 <a href="#data_objects">Data Objects</a>
73 <ol>
74 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070075 <a href="#observable_objects">Observable Objects</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070076 </li>
77
78 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070079 <a href="#observablefields">ObservableFields</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070080 </li>
81
82 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070083 <a href="#observable_collections">Observable Collections</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070084 </li>
85 </ol>
86 </li>
87
88 <li>
89 <a href="#generated_binding">Generated Binding</a>
90 <ol>
91 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070092 <a href="#creating">Creating</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070093 </li>
94
95 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070096 <a href="#views_with_ids">Views With IDs</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070097 </li>
98
99 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700100 <a href="#variables">Variables</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700101 </li>
102
103 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700104 <a href="#viewstubs">ViewStubs</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700105 </li>
106
107 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700108 <a href="#advanced_binding">Advanced Binding</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700109 </li>
110 </ol>
111 </li>
112
113 <li>
114 <a href="#attribute_setters">Attribute Setters</a>
115 <ol>
116 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700117 <a href="#automatic_setters">Automatic Setters</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700118 </li>
119
120 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700121 <a href="#renamed_setters">Renamed Setters</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700122 </li>
123
124 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700125 <a href="#custom_setters">Custom Setters</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700126 </li>
127 </ol>
128 </li>
129
130 <li>
131 <a href="#converters">Converters</a>
132 <ol>
133 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700134 <a href="#object_conversions">Object Conversions</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700135 </li>
136
137 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700138 <a href="#custom_conversions">Custom Conversions</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700139 </li>
140 </ol>
141 </li>
Daniel Yudaa41bb2015-12-08 10:58:07 -0800142
143 <li>
144 <a href="#studio_support">Android Studio Support for Data Binding</a>
145 </li>
146
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700147 </ol>
148 </div><!-- qv -->
149</div><!-- qv-wrapper -->
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700150
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700151<p>
152 This document explains how to use the Data Binding Library to write
153 declarative layouts and minimize the glue code necessary to bind your
154 application logic and layouts.
155</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700156
Yigit Boyar05eaab62016-05-25 10:45:01 -0700157<p>
158 The Data Binding Library offers both flexibility and broad compatibility —
159 it's a support library, so you can use it with all Android platform versions
160 back to <strong>Android 2.1</strong> (API level 7+).
161</p>
Dirk Dougherty08710f12015-05-28 22:01:36 -0700162
Yigit Boyar05eaab62016-05-25 10:45:01 -0700163<p>
164 To use data binding, Android Plugin for Gradle <strong>1.5.0-alpha1</strong>
165 or higher is required.
166</p>
Dirk Dougherty08710f12015-05-28 22:01:36 -0700167
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700168<h2 id="build_environment">
169 Build Environment
170</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700171
sreevanis1a1d5db2015-10-30 14:44:51 -0700172<p>
Yigit Boyar05eaab62016-05-25 10:45:01 -0700173 To get started with Data Binding, download the library from the Support
174 repository in the Android SDK manager.
sreevanis0cd62032015-11-03 09:57:57 -0800175</p>
176
Yigit Boyar05eaab62016-05-25 10:45:01 -0700177<p>
178 To configure your app to use data binding, add the <code>dataBinding</code>
179 element to your <code>build.gradle</code> file in the app module.
180</p>
sreevanis1a1d5db2015-10-30 14:44:51 -0700181
Yigit Boyar05eaab62016-05-25 10:45:01 -0700182<p>
183 Use the following code snippet to configure data binding:
184</p>
sreevanis1a1d5db2015-10-30 14:44:51 -0700185<pre>
186android {
187 ....
188 dataBinding {
189 enabled = true
190 }
191}
192</pre>
Yigit Boyar05eaab62016-05-25 10:45:01 -0700193<p>
194 If you have an app module that depends on a library which uses data binding,
195 your app module must configure data binding in its <code>build.gradle</code>
196 file as well.
197</p>
Dirk Dougherty08710f12015-05-28 22:01:36 -0700198
Yigit Boyar05eaab62016-05-25 10:45:01 -0700199<p>
200 Also, make sure you are using a compatible version of Android Studio.
201 <strong>Android Studio 1.3</strong> and later provides support for data
202 binding as described in <a href="#studio_support">Android Studio Support for
203 Data Binding</a>.
Daniel Yudaa41bb2015-12-08 10:58:07 -0800204</p>
Dirk Dougherty08710f12015-05-28 22:01:36 -0700205
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700206<h2 id="data_binding_layout_files">
207 Data Binding Layout Files
208</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700209
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700210<h3 id="writing_expressions">
Yigit Boyar05eaab62016-05-25 10:45:01 -0700211 Writing your first set of data binding expressions
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700212</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700213
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700214<p>
215 Data-binding layout files are slightly different and start with a root tag of
216 <strong>layout</strong> followed by a <strong>data</strong> element and a
217 <strong>view</strong> root element. This view element is what your root would
218 be in a non-binding layout file. A sample file looks like this:
219</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700220
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700221<pre>
George Mount4ba18202015-07-27 12:39:28 -0700222&lt;?xml version="1.0" encoding="utf-8"?&gt;
223&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"&gt;
224 &lt;data&gt;
225 &lt;variable name="user" type="com.example.User"/&gt;
226 &lt;/data&gt;
227 &lt;LinearLayout
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700228 android:orientation="vertical"
229 android:layout_width="match_parent"
George Mount4ba18202015-07-27 12:39:28 -0700230 android:layout_height="match_parent"&gt;
231 &lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700232 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700233 android:text="&commat;{user.firstName}"/&gt;
234 &lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700235 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700236 android:text="&commat;{user.lastName}"/&gt;
237 &lt;/LinearLayout&gt;
238&lt;/layout&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700239</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700240<p>
241 The user <strong>variable</strong> within <strong>data</strong> describes a
242 property that may be used within this layout.
243</p>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700244<pre>
245&lt;<strong>variable name="user" type="com.example.User"</strong>/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700246</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700247<p>
248 Expressions within the layout are written in the attribute properties using
Mark Lu011c07b2016-07-28 11:15:11 -0700249 the "<code>&commat;{}</code>" syntax. Here, the TextView's text is set to
Yigit Boyar05eaab62016-05-25 10:45:01 -0700250 the firstName property of user:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700251</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700252
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700253<pre>
George Mount4ba18202015-07-27 12:39:28 -0700254&lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700255 android:layout_height="wrap_content"
Mark Lu011c07b2016-07-28 11:15:11 -0700256 android:text="&commat;{user.firstName}"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700257</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700258<h3 id="data_object">
259 Data Object
260</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700261
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700262<p>
Mark Lu011c07b2016-07-28 11:15:11 -0700263 Let's assume for now that you have a plain-old Java object (POJO) for User:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700264</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700265
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700266<pre>
George Mount4ba18202015-07-27 12:39:28 -0700267public class User {
268 public final String firstName;
269 public final String lastName;
270 public User(String firstName, String lastName) {
271 this.firstName = firstName;
272 this.lastName = lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700273 }
274}
275</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700276<p>
277 This type of object has data that never changes. It is common in applications
278 to have data that is read once and never changes thereafter. It is also
279 possible to use a JavaBeans objects:
280</p>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700281<pre>
George Mount4ba18202015-07-27 12:39:28 -0700282public class User {
283 private final String firstName;
284 private final String lastName;
285 public User(String firstName, String lastName) {
286 this.firstName = firstName;
287 this.lastName = lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700288 }
George Mount4ba18202015-07-27 12:39:28 -0700289 public String getFirstName() {
290 return this.firstName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700291 }
George Mount4ba18202015-07-27 12:39:28 -0700292 public String getLastName() {
293 return this.lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700294 }
295}
296</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700297<p>
298 From the perspective of data binding, these two classes are equivalent. The
Mark Lu011c07b2016-07-28 11:15:11 -0700299 expression <strong><code>&commat;{user.firstName}</code></strong> used
300 for the TextView's <strong><code>android:text</code></strong> attribute will
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700301 access the <strong><code>firstName</code></strong> field in the former class
Yigit Boyar05eaab62016-05-25 10:45:01 -0700302 and the <code>getFirstName()</code> method in the latter class.
303 Alternatively, it will also be resolved to <code>firstName()</code> if that
304 method exists.
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700305</p>
306
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700307<h3 id="binding_data">
308 Binding Data
309</h3>
310
311<p>
312 By default, a Binding class will be generated based on the name of the layout
Mark Lu011c07b2016-07-28 11:15:11 -0700313 file, converting it to Pascal case and suffixing "Binding" to it. The above
George Mount4ba18202015-07-27 12:39:28 -0700314 layout file was <code>main_activity.xml</code> so the generate class was
315 <code>MainActivityBinding</code>. This class holds all the bindings from the
Mark Lu011c07b2016-07-28 11:15:11 -0700316 layout properties (e.g. the <code>user</code> variable) to the layout's Views
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700317 and knows how to assign values for the binding expressions.The easiest means
318 for creating the bindings is to do it while inflating:
319</p>
320
321<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700322&commat;Override
George Mount4ba18202015-07-27 12:39:28 -0700323protected void onCreate(Bundle savedInstanceState) {
324 super.onCreate(savedInstanceState);
325 MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
326 User user = new User("Test", "User");
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700327 binding.setUser(user);
328}
329</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700330<p>
Mark Lu011c07b2016-07-28 11:15:11 -0700331 You're done! Run the application and you'll see Test User in the UI.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700332 Alternatively, you can get the view via:
333</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700334
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700335<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700336MainActivityBinding binding = MainActivityBinding.<em>inflate</em>(getLayoutInflater());
337</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700338<p>
339 If you are using data binding items inside a ListView or RecyclerView
340 adapter, you may prefer to use:
341</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700342
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700343<pre>
George Mount4ba18202015-07-27 12:39:28 -0700344ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700345//or
346ListItemBinding binding = DataBindingUtil.<em>inflate</em>(layoutInflater, R.layout.<em><strong>list_item</strong></em>, viewGroup, <strong>false</strong>);
347</pre>
Yigit Boyar05eaab62016-05-25 10:45:01 -0700348<h3 id="event_handling">Event Handling</h3>
George Mount4ba18202015-07-27 12:39:28 -0700349<p>
Yigit Boyar05eaab62016-05-25 10:45:01 -0700350Data Binding allows you to write expressions handling events that are dispatched from the views (e.g. onClick).
351Event attribute names are governed by the name of the listener method with a few exceptions.
352For example, {@link android.view.View.OnLongClickListener} has a method {@link android.view.View.OnLongClickListener#onLongClick onLongClick()},
353so the attribute for this event is <code>android:onLongClick</code>.
354There are two ways to handle an event.
355</p>
356<ul>
357 <li>
358 <a href="#method_references">Method References</a>: In your expressions, you can reference methods that conform to the signature of the listener method. When an expression evaluates to a method reference, Data Binding wraps the method reference and owner object in a listener, and sets that listener on the target view. If the expression evaluates to null, Data Binding does not create a listener and sets a null listener instead.
359 </li>
360 <li>
361 <a href="#listener_bindings">Listener Bindings</a>: These are lambda expressions that are evaluated when the event happens.
362Data Binding always creates a listener, which it sets on the view. When the event is dispatched, the listener evaluates the lambda expression.
363 </li>
364</ul>
365<h4 id="method_references">
366 Method References
367</h4>
368<p>
369 Events can be bound to handler methods directly, similar to the way
370 <strong><code>android:onClick</code></strong> can be assigned to a method in an Activity.
371 One major advantage compared to the {@code View#onClick} attribute is that the expression
372 is processed at compile time, so if the method does not exist or its signature is not
373 correct, you receive a compile time error.</p>
374<p>
375 The major difference between Method References and Listener Bindings is that
376 the actual listener implementation is created when the data is bound, not
377 when the event is triggered. If you prefer to evaluate the expression when
378 the event happens, you should use <a href="#listener_bindings">listener
379 binding</a>.
George Mount4ba18202015-07-27 12:39:28 -0700380</p>
381<p>
382 To assign an event to its handler, use a normal binding expression, with the value
383 being the method name to call. For example, if your data object has two methods:
384</p>
385<pre>public class MyHandlers {
386 public void onClickFriend(View view) { ... }
George Mount4ba18202015-07-27 12:39:28 -0700387}
388</pre>
389<p>
390 The binding expression can assign the click listener for a View:
391</p>
392<pre>
393&lt;?xml version="1.0" encoding="utf-8"?&gt;
394&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"&gt;
395 &lt;data&gt;
396 &lt;variable name="handlers" type="com.example.Handlers"/&gt;
397 &lt;variable name="user" type="com.example.User"/&gt;
398 &lt;/data&gt;
399 &lt;LinearLayout
400 android:orientation="vertical"
401 android:layout_width="match_parent"
402 android:layout_height="match_parent"&gt;
403 &lt;TextView android:layout_width="wrap_content"
404 android:layout_height="wrap_content"
405 android:text="&commat;{user.firstName}"
Yigit Boyar05eaab62016-05-25 10:45:01 -0700406 android:onClick="&commat;{handlers::onClickFriend}"/&gt;
George Mount4ba18202015-07-27 12:39:28 -0700407 &lt;/LinearLayout&gt;
408&lt;/layout&gt;
409</pre>
Yigit Boyar05eaab62016-05-25 10:45:01 -0700410<p>
411Note that the signature of the method in the expression must exactly match the signature of the method in the
412Listener object.
413</p>
414<h4 id="listener_bindings">
415 Listener Bindings
416</h4>
417<p>
418 Listener Bindings are binding expressions that run when an event happens.
419 They are similar to method references, but they let you run arbitrary data
420 binding expressions. This feature is available with Android Gradle Plugin for Gradle
421 version 2.0 and later.
422</p>
423<p>
424 In method references, the parameters of the method must
425 match the parameters of the event listener. In Listener Bindings, only your
426 return value must match the expected return value of the listener (unless it
427 is expecting void).
428 For example, you can have a presenter class that has the following method:
429</p>
430<pre>
431public class Presenter {
432 public void onSaveClick(Task task){}
433}
434</pre>
435 Then you can bind the click event to your class as follows:
436<pre>
Mark Lu011c07b2016-07-28 11:15:11 -0700437 &lt;?xml version="1.0" encoding="utf-8"?&gt;
438 &lt;layout xmlns:android="http://schemas.android.com/apk/res/android"&gt;
Yigit Boyar05eaab62016-05-25 10:45:01 -0700439 &lt;data&gt;
Mark Lu011c07b2016-07-28 11:15:11 -0700440 &lt;variable name="task" type="com.android.example.Task" /&gt;
441 &lt;variable name="presenter" type="com.android.example.Presenter" /&gt;
Yigit Boyar05eaab62016-05-25 10:45:01 -0700442 &lt;/data&gt;
Mark Lu011c07b2016-07-28 11:15:11 -0700443 &lt;LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"&gt;
444 &lt;Button android:layout_width="wrap_content" android:layout_height="wrap_content"
445 android:onClick="@{() -&gt; presenter.onSaveClick(task)}" /&gt;
Yigit Boyar05eaab62016-05-25 10:45:01 -0700446 &lt;/LinearLayout&gt;
447 &lt;/layout&gt;
448</pre>
449<p>
450 Listeners are represented by lambda expressions that are allowed only as root
451 elements of your expressions. When a callback is used in an expression, Data
452 Binding automatically creates the necessary listener and registers for the
453 event. When the view fires the event, Data Binding evaluates the given
454 expression. As in regular binding expressions, you still get the null and
455 thread safety of Data Binding while these listener expressions are being
456 evaluated.
457</p>
458<p>
459 Note that in the example above, we haven't defined the {@code view} parameter
460 that is passed into {@link
461 android.view.View.OnClickListener#onClick(android.view.View view)}. Listener
462 bindings provide two choices for listener parameters: you can either ignore
463 all parameters to the method or name all of them. If you prefer to name the
464 parameters, you can use them in your expression. For example, the expression
465 above could be written as:
466</p>
467<pre>
Mark Lu011c07b2016-07-28 11:15:11 -0700468 android:onClick="@{(view) -&gt; presenter.onSaveClick(task)}"
Yigit Boyar05eaab62016-05-25 10:45:01 -0700469</pre>
470Or if you wanted to use the parameter in the expression, it could work as follows:
471<pre>
472public class Presenter {
473 public void onSaveClick(View view, Task task){}
474}
475</pre>
476<pre>
Mark Lu011c07b2016-07-28 11:15:11 -0700477 android:onClick="@{(theView) -&gt; presenter.onSaveClick(theView, task)}"
Yigit Boyar05eaab62016-05-25 10:45:01 -0700478</pre>
479You can use a lambda expression with more than one parameter:
480<pre>
481public class Presenter {
482 public void onCompletedChanged(Task task, boolean completed){}
483}
484</pre>
485<pre>
Mark Lu011c07b2016-07-28 11:15:11 -0700486 &lt;CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content"
487 android:onCheckedChanged="@{(cb, isChecked) -&gt; presenter.completeChanged(task, isChecked)}" /&gt;
Yigit Boyar05eaab62016-05-25 10:45:01 -0700488</pre>
489<p>
490 If the event you are listening to returns a value whose type is not {@code
491 void}, your expressions must return the same type of value as well. For
492 example, if you want to listen for the long click event, your expression
493 should return {@code boolean}.
494</p>
495<pre>
496public class Presenter {
497 public boolean onLongClick(View view, Task task){}
498}
499</pre>
500<pre>
Mark Lu011c07b2016-07-28 11:15:11 -0700501 android:onLongClick="@{(theView) -&gt; presenter.onLongClick(theView, task)}"
Yigit Boyar05eaab62016-05-25 10:45:01 -0700502</pre>
503<p>
504If the expression cannot be evaluated due to {@code null} objects, Data Binding returns
505the default Java value for that type. For example, {@code null} for reference types, {@code 0} for {@code int},
506{@code false} for {@code boolean}, etc.
507</p>
508<p>
509If you need to use an expression with a predicate (e.g. ternary), you can use
510{@code void} as a symbol.
511</p>
512<pre>
Mark Lu011c07b2016-07-28 11:15:11 -0700513 android:onClick="@{(v) -&gt; v.isVisible() ? doSomething() : void}"
Yigit Boyar05eaab62016-05-25 10:45:01 -0700514</pre>
515
516<h5>Avoid Complex Listeners</h5>
517Listener expressions are very powerful and can make your code very easy to read.
Mark Luc4a01392016-07-18 10:42:11 -0700518On the other hand, listeners containing complex expressions make your layouts hard to read and unmaintainable.
519These expressions should be as simple as passing available data from your UI to your callback method. You should implement
Yigit Boyar05eaab62016-05-25 10:45:01 -0700520any business logic inside the callback method that you invoked from the listener expression.
George Mount9b332f32016-01-28 14:31:25 -0800521
522<p>
523 Some specialized click event handlers exist and they need an attribute other than
524 <code>android:onClick</code> to avoid a conflict. The following attributes have been created
525 to avoid such conflicts:
526</p>
527
528<table>
529 <tr>
530 <th>Class</th>
531 <th>Listener Setter</th>
532 <th>Attribute</th>
533 </tr>
534 <tr>
535 <td>{@link android.widget.SearchView}</td>
536 <td>{@link android.widget.SearchView#setOnSearchClickListener}</td>
537 <td><code>android:onSearchClick</code></td>
538 </tr>
539 <tr>
540 <td>{@link android.widget.ZoomControls}</td>
541 <td>{@link android.widget.ZoomControls#setOnZoomInClickListener}</td>
542 <td><code>android:onZoomIn</code></td>
543 </tr>
544 <tr>
545 <td>{@link android.widget.ZoomControls}</td>
546 <td>{@link android.widget.ZoomControls#setOnZoomOutClickListener}</td>
547 <td><code>android:onZoomOut</code></td>
548 </tr>
549</table>
550
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700551<h2 id="layout_details">
552 Layout Details
553</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700554
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700555<h3 id="imports">
556 Imports
557</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700558
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700559<p>
560 Zero or more <strong><code>import</code></strong> elements may be used inside
561 the <strong><code>data</code></strong> element. These allow easy reference to
562 classes inside your layout file, just like in Java.
563</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700564
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700565<pre>
George Mount4ba18202015-07-27 12:39:28 -0700566&lt;data&gt;
567 &lt;import type="android.view.View"/&gt;
568&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700569</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700570<p>
571 Now, View may be used within your binding expression:
572</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700573
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700574<pre>
George Mount4ba18202015-07-27 12:39:28 -0700575&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700576 android:text="&commat;{user.lastName}"
577 android:layout_width="wrap_content"
578 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700579 android:visibility="&commat;{user.isAdult ? View.VISIBLE : View.GONE}"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700580</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700581<p>
582 When there are class name conflicts, one of the classes may be renamed to an
Mark Lu011c07b2016-07-28 11:15:11 -0700583 "alias:"
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700584</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700585
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700586<pre>
George Mount4ba18202015-07-27 12:39:28 -0700587&lt;import type="android.view.View"/&gt;
588&lt;import type="com.example.real.estate.View"
589 alias="Vista"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700590</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700591<p>
592 Now, <strong><code>Vista</code></strong> may be used to reference the
593 <code>com.example.real.estate.View</code> and
594 <strong><code>View</code></strong> may be used to reference
595 <code>android.view.View</code> within the layout file. Imported types may be
596 used as type references in variables and expressions:
597</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700598
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700599<pre>
George Mount4ba18202015-07-27 12:39:28 -0700600&lt;data&gt;
601 &lt;import type="com.example.User"/&gt;
602 &lt;import type="java.util.List"/&gt;
603 &lt;variable name="user" type="User"/&gt;
Mark Lub1b5efd2016-08-04 14:45:42 -0700604 &lt;variable name="userList" type="List&amp;lt;User&amp;gt;"/&gt;
George Mount4ba18202015-07-27 12:39:28 -0700605&lt;/data&gt;
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700606</pre>
Dirk Dougherty08710f12015-05-28 22:01:36 -0700607<p class="caution">
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700608 <strong>Note</strong>: Android Studio does not yet handle imports so the
609 autocomplete for imported variables may not work in your IDE. Your
610 application will still compile fine and you can work around the IDE issue by
611 using fully qualified names in your variable definitions.
612</p>
613
614<pre>
George Mount4ba18202015-07-27 12:39:28 -0700615&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700616 android:text="&commat;{((User)(user.connection)).lastName}"
617 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700618 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700619</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700620<p>
621 Imported types may also be used when referencing static fields and methods in
622 expressions:
623</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700624
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700625<pre>
George Mount4ba18202015-07-27 12:39:28 -0700626&lt;data&gt;
627 &lt;import type="com.example.MyStringUtils"/&gt;
628 &lt;variable name="user" type="com.example.User"/&gt;
629&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700630…
George Mount4ba18202015-07-27 12:39:28 -0700631&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700632 android:text="&commat;{MyStringUtils.capitalize(user.lastName)}"
633 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700634 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700635</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700636<p>
637 Just as in Java, <code>java.lang.*</code> is imported automatically.
638</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700639
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700640<h3 id="variables">
641 Variables
642</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700643
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700644<p>
645 Any number of <strong><code>variable</code></strong> elements may be used
646 inside the <strong><code>data</code></strong> element. Each
647 <strong><code>variable</code></strong> element describes a property that may
648 be set on the layout to be used in binding expressions within the layout
649 file.
650</p>
651
652<pre>
George Mount4ba18202015-07-27 12:39:28 -0700653&lt;data&gt;
654 &lt;import type="android.graphics.drawable.Drawable"/&gt;
655 &lt;variable name="user" type="com.example.User"/&gt;
656 &lt;variable name="image" type="Drawable"/&gt;
657 &lt;variable name="note" type="String"/&gt;
658&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700659</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700660<p>
661 The variable types are inspected at compile time, so if a variable implements
George Mount4ba18202015-07-27 12:39:28 -0700662 {@link android.databinding.Observable} or is an <a href=
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700663 "#observable_collections">observable collection</a>, that should be reflected
664 in the type. If the variable is a base class or interface that does not
665 implement the Observable* interface, the variables will <strong>not
666 be</strong> observed!
667</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700668
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700669<p>
670 When there are different layout files for various configurations (e.g.
671 landscape or portrait), the variables will be combined. There must not be
672 conflicting variable definitions between these layout files.
673</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700674
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700675<p>
676 The generated binding class will have a setter and getter for each of the
677 described variables. The variables will take the default Java values until
678 the setter is called &mdash; <code>null</code> for reference types,
679 <code>0</code> for <code>int</code>, <code>false</code> for
680 <code>boolean</code>, etc.
681</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700682
George Mount9b332f32016-01-28 14:31:25 -0800683<p>
684 A special variable named <code>context</code> is generated for use in binding
685 expressions as needed. The value for <code>context</code> is the
686 <code>Context</code> from the root View's {@link android.view.View#getContext}.
687 The <code>context</code> variable will be overridden by an explicit variable
688 declaration with that name.
689</p>
690
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700691<h3 id="custom_binding_class_names">
692 Custom Binding Class Names
693</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700694
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700695<p>
696 By default, a Binding class is generated based on the name of the layout
697 file, starting it with upper-case, removing underscores ( _ ) and
Mark Lu011c07b2016-07-28 11:15:11 -0700698 capitalizing the following letter and then suffixing "Binding". This class
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700699 will be placed in a databinding package under the module package. For
700 example, the layout file <code>contact_item.xml</code> will generate
701 <code>ContactItemBinding</code>. If the module package is
702 <code>com.example.my.app</code>, then it will be placed in
703 <code>com.example.my.app.databinding</code>.
704</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700705
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700706<p>
707 Binding classes may be renamed or placed in different packages by adjusting
708 the <strong><code>class</code></strong> attribute of the
709 <strong><code>data</code></strong> element. For example:
710</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700711
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700712<pre>
George Mount4ba18202015-07-27 12:39:28 -0700713&lt;data class="ContactItem"&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700714 ...
George Mount4ba18202015-07-27 12:39:28 -0700715&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700716</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700717<p>
718 This generates the binding class as <code>ContactItem</code> in the
719 databinding package in the module package. If the class should be generated
720 in a different package within the module package, it may be prefixed with
Mark Lu011c07b2016-07-28 11:15:11 -0700721 ".":
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700722</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700723
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700724<pre>
George Mount4ba18202015-07-27 12:39:28 -0700725&lt;data class=".ContactItem"&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700726 ...
George Mount4ba18202015-07-27 12:39:28 -0700727&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700728</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700729<p>
730 In this case, <code>ContactItem</code> is generated in the module package
731 directly. Any package may be used if the full package is provided:
732</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700733
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700734<pre>
George Mount4ba18202015-07-27 12:39:28 -0700735&lt;data class="com.example.ContactItem"&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700736 ...
George Mount4ba18202015-07-27 12:39:28 -0700737&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700738</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700739<h3 id="includes">
740 Includes
741</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700742
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700743<p>
Mark Lu011c07b2016-07-28 11:15:11 -0700744 Variables may be passed into an included layout's binding from the
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700745 containing layout by using the application namespace and the variable name in
746 an attribute:
747</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700748
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700749<pre>
George Mount4ba18202015-07-27 12:39:28 -0700750&lt;?xml version="1.0" encoding="utf-8"?&gt;
751&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"
752 xmlns:bind="http://schemas.android.com/apk/res-auto"&gt;
753 &lt;data&gt;
754 &lt;variable name="user" type="com.example.User"/&gt;
755 &lt;/data&gt;
756 &lt;LinearLayout
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700757 android:orientation="vertical"
758 android:layout_width="match_parent"
George Mount4ba18202015-07-27 12:39:28 -0700759 android:layout_height="match_parent"&gt;
760 &lt;include layout="&commat;layout/name"
761 bind:user="&commat;{user}"/&gt;
762 &lt;include layout="&commat;layout/contact"
763 bind:user="&commat;{user}"/&gt;
764 &lt;/LinearLayout&gt;
765&lt;/layout&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700766</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700767<p>
768 Here, there must be a <code>user</code> variable in both the
769 <code>name.xml</code> and <code>contact.xml</code> layout files.
770</p>
George Mount4ba18202015-07-27 12:39:28 -0700771<p>
772 Data binding does not support include as a direct child of a merge element. For example,
773 <strong>the following layout is not supported:</strong>
774</p>
775<pre>
776&lt;?xml version="1.0" encoding="utf-8"?&gt;
777&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"
778 xmlns:bind="http://schemas.android.com/apk/res-auto"&gt;
779 &lt;data&gt;
780 &lt;variable name="user" type="com.example.User"/&gt;
781 &lt;/data&gt;
782 &lt;merge&gt;
783 &lt;include layout="&commat;layout/name"
784 bind:user="&commat;{user}"/&gt;
785 &lt;include layout="&commat;layout/contact"
786 bind:user="&commat;{user}"/&gt;
787 &lt;/merge&gt;
788&lt;/layout&gt;
789</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700790<h3 id="expression_language">
791 Expression Language
792</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700793
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700794<h4 id="common_features">
795 Common Features
796</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700797
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700798<p>
799 The expression language looks a lot like a Java expression. These are the
800 same:
801</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700802
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700803<ul>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700804 <li>Mathematical <strong><code>+ - / * %</code></strong>
805 </li>
806
807 <li>String concatenation <strong><code>+</code></strong>
808 </li>
809
810 <li>
George Mount4ba18202015-07-27 12:39:28 -0700811 Logical <strong><code>&& ||</code></strong>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700812 </li>
813
George Mount4ba18202015-07-27 12:39:28 -0700814 <li>Binary <strong><code>& | ^</code></strong>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700815 </li>
816
817 <li>Unary <strong><code>+ - ! ~</code></strong>
818 </li>
819
820 <li>Shift <strong><code>&gt;&gt; &gt;&gt;&gt; &lt;&lt;</code></strong>
821 </li>
822
823 <li>Comparison <strong><code>== &gt; &lt; &gt;= &lt;=</code></strong>
824 </li>
825
826 <li>
827 <strong><code>instanceof</code></strong>
828 </li>
829
830 <li>Grouping <strong><code>()</code></strong>
831 </li>
832
833 <li>Literals - character, String, numeric, <strong><code>null</code></strong>
834 </li>
835
836 <li>Cast
837 </li>
838
839 <li>Method calls
840 </li>
841
842 <li>Field access
843 </li>
844
845 <li>Array access <strong><code>[]</code></strong>
846 </li>
847
848 <li>Ternary operator <strong><code>?:</code></strong>
849 </li>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700850</ul>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700851
852<p>
853 Examples:
854</p>
855
856<pre>
George Mount4ba18202015-07-27 12:39:28 -0700857android:text="&commat;{String.valueOf(index + 1)}"
Mark Lu011c07b2016-07-28 11:15:11 -0700858android:visibility="&commat;{age &lt; 13 ? View.GONE : View.VISIBLE}"
859android:transitionName='&commat;{"image_" + id}'
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700860</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700861<h4 id="missing_operations">
862 Missing Operations
863</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700864
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700865<p>
866 A few operations are missing from the expression syntax that you can use in
867 Java.
868</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700869
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700870<ul>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700871 <li>
872 <strong><code>this</code></strong>
873 </li>
874
875 <li>
876 <strong><code>super</code></strong>
877 </li>
878
879 <li>
880 <strong><code>new</code></strong>
881 </li>
882
883 <li>Explicit generic invocation
884 </li>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700885</ul>
886
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700887<h4 id="null_coalescing_operator">
888 Null Coalescing Operator
889</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700890
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700891<p>
892 The null coalescing operator (<strong><code>??</code></strong>) chooses the
893 left operand if it is not null or the right if it is null.
894</p>
895
896<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700897<strong>android:text="&commat;{user.displayName ?? user.lastName}"</strong>
898</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700899<p>
900 This is functionally equivalent to:
901</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700902
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700903<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700904<strong>android:text="&commat;{user.displayName != null ? user.displayName : user.lastName}"</strong>
905</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700906<h4 id="property_reference">
907 Property Reference
908</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700909
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700910<p>
911 The first was already discussed in the <a href=
912 "#writing_your_first_data_binding_expressions">Writing your first data
913 binding expressions</a> above: short form JavaBean references. When an
914 expression references a property on a class, it uses the same format for
915 fields, getters, and ObservableFields.
916</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700917
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700918<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700919<strong>android:text="&commat;{user.lastName}"</strong>
920</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700921<h4>
922 Avoiding NullPointerException
923</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700924
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700925<p>
926 Generated data binding code automatically checks for nulls and avoid null
927 pointer exceptions. For example, in the expression
928 <code>&commat;{user.name}</code>, if <code>user</code> is null,
929 <code>user.name</code> will be assigned its default value (null). If you were
930 referencing <code>user.age</code>, where age is an <code>int</code>, then it
931 would default to 0.
932</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700933
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700934<h4 id="collections">
935 Collections
936</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700937
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700938<p>
939 Common collections: arrays, lists, sparse lists, and maps, may be accessed
940 using the <code>[]</code> operator for convenience.
941</p>
942
943<pre>
George Mount4ba18202015-07-27 12:39:28 -0700944&lt;data&gt;
945 &lt;import type="android.util.SparseArray"/&gt;
946 &lt;import type="java.util.Map"/&gt;
947 &lt;import type="java.util.List"/&gt;
Mark Lub1b5efd2016-08-04 14:45:42 -0700948 &lt;variable name="list" type="List&amp;lt;String&amp;gt;"/&gt;
949 &lt;variable name="sparse" type="SparseArray&amp;lt;String&amp;gt;"/&gt;
950 &lt;variable name="map" type="Map&amp;lt;String, String&amp;gt;"/&gt;
George Mount4ba18202015-07-27 12:39:28 -0700951 &lt;variable name="index" type="int"/&gt;
952 &lt;variable name="key" type="String"/&gt;
953&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700954…
George Mount4ba18202015-07-27 12:39:28 -0700955android:text="&commat;{list[index]}"
956…
957android:text="&commat;{sparse[index]}"
958…
959android:text="&commat;{map[key]}"
960
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700961</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700962<h4 id="string_literals">
963 String Literals
964</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700965
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700966<p>
967 When using single quotes around the attribute value, it is easy to use double
968 quotes in the expression:
969</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700970
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700971<pre>
Mark Lu011c07b2016-07-28 11:15:11 -0700972android:text='&commat;{map["firstName"]}'
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700973</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700974<p>
975 It is also possible to use double quotes to surround the attribute value.
Mark Lu011c07b2016-07-28 11:15:11 -0700976 When doing so, String literals should either use the ' or back quote
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700977 (`).
978</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700979
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700980<pre>
George Mount4ba18202015-07-27 12:39:28 -0700981android:text="&commat;{map[`firstName`}"
Mark Lu011c07b2016-07-28 11:15:11 -0700982android:text="&commat;{map['firstName']}"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700983</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700984<h4 id="resources">
985 Resources
986</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700987
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700988<p>
989 It is possible to access resources as part of expressions using the normal
990 syntax:
991</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700992
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700993<pre>
George Mount4ba18202015-07-27 12:39:28 -0700994android:padding="&commat;{large? &commat;dimen/largePadding : &commat;dimen/smallPadding}"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700995</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700996<p>
997 Format strings and plurals may be evaluated by providing parameters:
998</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700999
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001000<pre>
George Mount4ba18202015-07-27 12:39:28 -07001001android:text="&commat;{&commat;string/nameFormat(firstName, lastName)}"
1002android:text="&commat;{&commat;plurals/banana(bananaCount)}"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001003</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001004<p>
1005 When a plural takes multiple parameters, all parameters should be passed:
1006</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001007
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001008<pre>
1009
1010 Have an orange
1011 Have %d oranges
1012
George Mount4ba18202015-07-27 12:39:28 -07001013android:text="&commat;{&commat;plurals/orange(orangeCount, orangeCount)}"
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001014</pre>
1015<p>
1016 Some resources require explicit type evaluation.
1017</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001018
1019<table>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001020 <tr>
1021 <th>
1022 Type
1023 </th>
1024 <th>
1025 Normal Reference
1026 </th>
1027 <th>
1028 Expression Reference
1029 </th>
1030 </tr>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001031
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001032 <tr>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001033 <td>
George Mount4ba18202015-07-27 12:39:28 -07001034 String[]
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001035 </td>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001036 <td>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001037 &commat;array
1038 </td>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001039 <td>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001040 &commat;stringArray
1041 </td>
1042 </tr>
1043
1044 <tr>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001045 <td>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001046 int[]
1047 </td>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001048 <td>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001049 &commat;array
1050 </td>
1051 <td>
1052 &commat;intArray
1053 </td>
1054 </tr>
1055
1056 <tr>
1057 <td>
1058 TypedArray
1059 </td>
1060 <td>
1061 &commat;array
1062 </td>
1063 <td>
1064 &commat;typedArray
1065 </td>
1066 </tr>
1067
1068 <tr>
1069 <td>
1070 Animator
1071 </td>
1072 <td>
1073 &commat;animator
1074 </td>
1075 <td>
1076 &commat;animator
1077 </td>
1078 </tr>
1079
1080 <tr>
1081 <td>
1082 StateListAnimator
1083 </td>
1084 <td>
1085 &commat;animator
1086 </td>
1087 <td>
1088 &commat;stateListAnimator
1089 </td>
1090 </tr>
1091
1092 <tr>
1093 <td>
1094 color <code>int</code>
1095 </td>
1096 <td>
George Mount4ba18202015-07-27 12:39:28 -07001097 &commat;color
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001098 </td>
1099 <td>
1100 &commat;color
1101 </td>
1102 </tr>
1103
1104 <tr>
1105 <td>
1106 ColorStateList
1107 </td>
1108 <td>
1109 &commat;color
1110 </td>
1111 <td>
1112 &commat;colorStateList
1113 </td>
1114 </tr>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001115</table>
1116
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001117<h2 id="data_objects">
1118 Data Objects
1119</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001120
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001121<p>
1122 Any plain old Java object (POJO) may be used for data binding, but modifying
1123 a POJO will not cause the UI to update. The real power of data binding can be
1124 used by giving your data objects the ability to notify when data changes.
1125 There are three different data change notification mechanisms,
George Mount4ba18202015-07-27 12:39:28 -07001126 <a href="#observable_objects">Observable objects</a>,
1127 <a href="#observablefields">observable fields</a>, and
1128 <a href="#observable_collections">observable collection</a>s.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001129</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001130
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001131<p>
1132 When one of these observable data object is bound to the UI and a property of
1133 the data object changes, the UI will be updated automatically.
1134</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001135
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001136<h3 id="observable_objects">
1137 Observable Objects
1138</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001139
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001140<p>
George Mount4ba18202015-07-27 12:39:28 -07001141 A class implementing the {@link android.databinding.Observable} interface
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001142 will allow the binding to attach a single listener to a bound object to
1143 listen for changes of all properties on that object.
1144</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001145
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001146<p>
George Mount4ba18202015-07-27 12:39:28 -07001147 The {@link android.databinding.Observable} interface has a mechanism to add and remove
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001148 listeners, but notifying is up to the developer. To make development easier,
George Mount4ba18202015-07-27 12:39:28 -07001149 a base class, {@link android.databinding.BaseObservable}, was created to implement the
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001150 listener registration mechanism. The data class implementer is still
1151 responsible for notifying when the properties change. This is done by
George Mount4ba18202015-07-27 12:39:28 -07001152 assigning a {@link android.databinding.Bindable} annotation to the getter and notifying in
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001153 the setter.
1154</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001155
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001156<pre>
George Mount4ba18202015-07-27 12:39:28 -07001157private static class User extends BaseObservable {
1158 private String firstName;
1159 private String lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001160 &commat;Bindable
George Mount4ba18202015-07-27 12:39:28 -07001161 public String getFirstName() {
1162 return this.firstName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001163 }
1164 &commat;Bindable
George Mount4ba18202015-07-27 12:39:28 -07001165 public String getLastName() {
1166 return this.lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001167 }
George Mount4ba18202015-07-27 12:39:28 -07001168 public void setFirstName(String firstName) {
1169 this.firstName = firstName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001170 notifyPropertyChanged(BR.firstName);
1171 }
George Mount4ba18202015-07-27 12:39:28 -07001172 public void setLastName(String lastName) {
1173 this.lastName = lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001174 notifyPropertyChanged(BR.lastName);
1175 }
1176}
1177</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001178<p>
George Mount4ba18202015-07-27 12:39:28 -07001179 The {@link android.databinding.Bindable} annotation generates an entry in the BR class file
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001180 during compilation. The BR class file will be generated in the module
George Mount4ba18202015-07-27 12:39:28 -07001181 package. If the base class for data classes cannot be changed, the
1182 {@link android.databinding.Observable} interface may be implemented using the convenient
1183 {@link android.databinding.PropertyChangeRegistry} to store and notify listeners
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001184 efficiently.
1185</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001186
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001187<h3 id="observablefields">
1188 ObservableFields
1189</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001190
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001191<p>
George Mount4ba18202015-07-27 12:39:28 -07001192 A little work is involved in creating {@link android.databinding.Observable} classes, so
1193 developers who want to save time or have few properties may use
1194 {@link android.databinding.ObservableField} and its siblings
1195 {@link android.databinding.ObservableBoolean},
1196 {@link android.databinding.ObservableByte},
1197 {@link android.databinding.ObservableChar},
1198 {@link android.databinding.ObservableShort},
1199 {@link android.databinding.ObservableInt},
1200 {@link android.databinding.ObservableLong},
1201 {@link android.databinding.ObservableFloat},
1202 {@link android.databinding.ObservableDouble}, and
1203 {@link android.databinding.ObservableParcelable}.
1204 <code>ObservableFields</code> are self-contained observable objects that have a single
1205 field. The primitive versions avoid boxing and unboxing during access operations.
1206 To use, create a public final field in the data class:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001207</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001208
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001209<pre>
George Mount4ba18202015-07-27 12:39:28 -07001210private static class User {
1211 public final ObservableField&lt;String&gt; firstName =
1212 new ObservableField&lt;&gt;();
1213 public final ObservableField&lt;String&gt; lastName =
1214 new ObservableField&lt;&gt;();
1215 public final ObservableInt age = new ObservableInt();
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001216}
1217</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001218<p>
Mark Lu011c07b2016-07-28 11:15:11 -07001219 That's it! To access the value, use the set and get accessor methods:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001220</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001221
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001222<pre>
George Mount4ba18202015-07-27 12:39:28 -07001223user.firstName.set("Google");
1224int age = user.age.get();
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001225</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001226<h3 id="observable_collections">
1227 Observable Collections
1228</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001229
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001230<p>
1231 Some applications use more dynamic structures to hold data. Observable
George Mount4ba18202015-07-27 12:39:28 -07001232 collections allow keyed access to these data objects.
1233 {@link android.databinding.ObservableArrayMap} is
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001234 useful when the key is a reference type, such as String.
1235</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001236
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001237<pre>
George Mount4ba18202015-07-27 12:39:28 -07001238ObservableArrayMap&lt;String, Object&gt; user = new ObservableArrayMap&lt;&gt;();
1239user.put("firstName", "Google");
1240user.put("lastName", "Inc.");
1241user.put("age", 17);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001242</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001243<p>
1244 In the layout, the map may be accessed through the String keys:
1245</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001246
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001247<pre>
George Mount4ba18202015-07-27 12:39:28 -07001248&lt;data&gt;
1249 &lt;import type="android.databinding.ObservableMap"/&gt;
Mark Lub1b5efd2016-08-04 14:45:42 -07001250 &lt;variable name="user" type="ObservableMap&amp;lt;String, Object&amp;gt;"/&gt;
George Mount4ba18202015-07-27 12:39:28 -07001251&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001252…
George Mount4ba18202015-07-27 12:39:28 -07001253&lt;TextView
Mark Lu011c07b2016-07-28 11:15:11 -07001254 android:text='&commat;{user["lastName"]}'
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001255 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001256 android:layout_height="wrap_content"/&gt;
1257&lt;TextView
Mark Lu011c07b2016-07-28 11:15:11 -07001258 android:text='&commat;{String.valueOf(1 + (Integer)user["age"])}'
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001259 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001260 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001261</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001262<p>
George Mount4ba18202015-07-27 12:39:28 -07001263 {@link android.databinding.ObservableArrayList} is useful when the key is an integer:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001264</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001265
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001266<pre>
George Mount4ba18202015-07-27 12:39:28 -07001267ObservableArrayList&lt;Object&gt; user = new ObservableArrayList&lt;&gt;();
1268user.add("Google");
1269user.add("Inc.");
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001270user.add(17);
1271</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001272<p>
1273 In the layout, the list may be accessed through the indices:
1274</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001275
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001276<pre>
George Mount4ba18202015-07-27 12:39:28 -07001277&lt;data&gt;
1278 &lt;import type="android.databinding.ObservableList"/&gt;
1279 &lt;import type="com.example.my.app.Fields"/&gt;
Mark Lub1b5efd2016-08-04 14:45:42 -07001280 &lt;variable name="user" type="ObservableList&amp;lt;Object&amp;gt;"/&gt;
George Mount4ba18202015-07-27 12:39:28 -07001281&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001282…
George Mount4ba18202015-07-27 12:39:28 -07001283&lt;TextView
Mark Lu011c07b2016-07-28 11:15:11 -07001284 android:text='&commat;{user[Fields.LAST_NAME]}'
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001285 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001286 android:layout_height="wrap_content"/&gt;
1287&lt;TextView
Mark Lu011c07b2016-07-28 11:15:11 -07001288 android:text='&commat;{String.valueOf(1 + (Integer)user[Fields.AGE])}'
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001289 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001290 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001291</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001292<h2 id="generated_binding">
1293 Generated Binding
1294</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001295
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001296<p>
1297 The generated binding class links the layout variables with the Views within
1298 the layout. As discussed earlier, the name and package of the Binding may be
1299 <a href="#custom_binding_class_names">customized</a>. The Generated binding
George Mount4ba18202015-07-27 12:39:28 -07001300 classes all extend {@link android.databinding.ViewDataBinding}.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001301</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001302
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001303<h3 id="creating">
1304 Creating
1305</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001306
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001307<p>
1308 The binding should be created soon after inflation to ensure that the View
1309 hierarchy is not disturbed prior to binding to the Views with expressions
1310 within the layout. There are a few ways to bind to a layout. The most common
1311 is to use the static methods on the Binding class.The inflate method inflates
1312 the View hierarchy and binds to it all it one step. There is a simpler
George Mount4ba18202015-07-27 12:39:28 -07001313 version that only takes a {@link android.view.LayoutInflater} and one that takes a
1314 {@link android.view.ViewGroup} as well:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001315</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001316
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001317<pre>
George Mount4ba18202015-07-27 12:39:28 -07001318MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater);
1319MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001320</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001321<p>
1322 If the layout was inflated using a different mechanism, it may be bound
1323 separately:
1324</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001325
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001326<pre>
George Mount4ba18202015-07-27 12:39:28 -07001327MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001328</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001329<p>
1330 Sometimes the binding cannot be known in advance. In such cases, the binding
George Mount4ba18202015-07-27 12:39:28 -07001331 can be created using the {@link android.databinding.DataBindingUtil} class:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001332</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001333
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001334<pre>
George Mount4ba18202015-07-27 12:39:28 -07001335ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId,
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001336 parent, attachToParent);
George Mount4ba18202015-07-27 12:39:28 -07001337ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001338</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001339<h3 id="views_with_ids">
1340 Views With IDs
1341</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001342
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001343<p>
1344 A public final field will be generated for each View with an ID in the
1345 layout. The binding does a single pass on the View hierarchy, extracting the
1346 Views with IDs. This mechanism can be faster than calling findViewById for
1347 several Views. For example:
1348</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001349
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001350<pre>
George Mount4ba18202015-07-27 12:39:28 -07001351&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"&gt;
1352 &lt;data&gt;
1353 &lt;variable name="user" type="com.example.User"/&gt;
1354 &lt;/data&gt;
1355 &lt;LinearLayout
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001356 android:orientation="vertical"
1357 android:layout_width="match_parent"
George Mount4ba18202015-07-27 12:39:28 -07001358 android:layout_height="match_parent"&gt;
1359 &lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001360 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001361 android:text="&commat;{user.firstName}"
1362 android:id="&commat;+id/firstName"/&gt;
1363 &lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001364 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001365 android:text="&commat;{user.lastName}"
1366 android:id="&commat;+id/lastName"/&gt;
1367 &lt;/LinearLayout&gt;
1368&lt;/layout&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001369</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001370<p>
1371 Will generate a binding class with:
1372</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001373
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001374<pre>
George Mount4ba18202015-07-27 12:39:28 -07001375public final TextView firstName;
1376public final TextView lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001377</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001378<p>
1379 IDs are not nearly as necessary as without data binding, but there are still
1380 some instances where access to Views are still necessary from code.
1381</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001382
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001383<h3 id="variables2">
1384 Variables
1385</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001386
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001387<p>
1388 Each variable will be given accessor methods.
1389</p>
1390
1391<pre>
George Mount4ba18202015-07-27 12:39:28 -07001392&lt;data&gt;
1393 &lt;import type="android.graphics.drawable.Drawable"/&gt;
1394 &lt;variable name="user" type="com.example.User"/&gt;
1395 &lt;variable name="image" type="Drawable"/&gt;
1396 &lt;variable name="note" type="String"/&gt;
1397&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001398</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001399<p>
1400 will generate setters and getters in the binding:
1401</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001402
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001403<pre>
George Mount4ba18202015-07-27 12:39:28 -07001404public abstract com.example.User getUser();
1405public abstract void setUser(com.example.User user);
1406public abstract Drawable getImage();
1407public abstract void setImage(Drawable image);
1408public abstract String getNote();
1409public abstract void setNote(String note);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001410</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001411<h3 id="viewstubs">
1412 ViewStubs
1413</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001414
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001415<p>
George Mount4ba18202015-07-27 12:39:28 -07001416 {@link android.view.ViewStub}s are a little different from normal Views. They start off invisible
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001417 and when they either are made visible or are explicitly told to inflate, they
1418 replace themselves in the layout by inflating another layout.
1419</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001420
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001421<p>
George Mount4ba18202015-07-27 12:39:28 -07001422 Because the <code>ViewStub</code> essentially disappears from the View hierarchy, the View
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001423 in the binding object must also disappear to allow collection. Because the
George Mount4ba18202015-07-27 12:39:28 -07001424 Views are final, a {@link android.databinding.ViewStubProxy} object takes the place of the
1425 <code>ViewStub</code>, giving the developer access to the ViewStub when it exists and also
1426 access to the inflated View hierarchy when the <code>ViewStub</code> has been inflated.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001427</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001428
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001429<p>
1430 When inflating another layout, a binding must be established for the new
Mark Lu011c07b2016-07-28 11:15:11 -07001431 layout. Therefore, the <code>ViewStubProxy</code> must listen to the <code>ViewStub</code>'s
George Mount4ba18202015-07-27 12:39:28 -07001432 {@link android.view.ViewStub.OnInflateListener} and establish the binding at that time. Since
1433 only one can exist, the <code>ViewStubProxy</code> allows the developer to set an
1434 <code>OnInflateListener</code> on it that it will call after establishing the binding.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001435</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001436
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001437<h3 id="advanced_binding">
1438 Advanced Binding
1439</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001440
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001441<h4 id="dynamic_variables">
1442 Dynamic Variables
1443</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001444
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001445<p>
Mark Lu011c07b2016-07-28 11:15:11 -07001446 At times, the specific binding class won't be known. For example, a
George Mount4ba18202015-07-27 12:39:28 -07001447 {@link android.support.v7.widget.RecyclerView.Adapter} operating against arbitrary layouts
Mark Lu011c07b2016-07-28 11:15:11 -07001448 won't know the specific binding class. It still must assign the binding value during the
George Mount4ba18202015-07-27 12:39:28 -07001449 {@link android.support.v7.widget.RecyclerView.Adapter#onBindViewHolder}.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001450</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001451
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001452<p>
1453 In this example, all layouts that the RecyclerView binds to have an "item"
George Mount4ba18202015-07-27 12:39:28 -07001454 variable. The <code>BindingHolder</code> has a <code>getBinding</code> method returning the
1455 {@link android.databinding.ViewDataBinding} base.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001456</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001457
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001458<pre>
George Mount4ba18202015-07-27 12:39:28 -07001459public void onBindViewHolder(BindingHolder holder, int position) {
1460 final T item = mItems.get(position);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001461 holder.getBinding().setVariable(BR.item, item);
1462 holder.getBinding().executePendingBindings();
1463}
1464</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001465<h4 id="immediate_binding">
1466 Immediate Binding
1467</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001468
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001469<p>
1470 When a variable or observable changes, the binding will be scheduled to
1471 change before the next frame. There are times, however, when binding must be
1472 executed immediately. To force execution, use the
George Mount4ba18202015-07-27 12:39:28 -07001473 {@link android.databinding.ViewDataBinding#executePendingBindings()} method.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001474</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001475
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001476<h4>
1477 Background Thread
1478</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001479
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001480<p>
1481 You can change your data model in a background thread as long as it is not a
1482 collection. Data binding will localize each variable / field while evaluating
1483 to avoid any concurrency issues.
1484</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001485
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001486<h2 id="attribute_setters">
1487 Attribute Setters
1488</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001489
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001490<p>
1491 Whenever a bound value changes, the generated binding class must call a
1492 setter method on the View with the binding expression. The data binding
1493 framework has ways to customize which method to call to set the value.
1494</p>
1495
1496<h3 id="automatic_setters">
1497 Automatic Setters
1498</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001499For an attribute, data binding tries to find the method setAttribute. The
1500namespace for the attribute does not matter, only the attribute name itself.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001501<p>
Mark Lu011c07b2016-07-28 11:15:11 -07001502 For example, an expression associated with TextView's attribute
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001503 <strong><code>android:text</code></strong> will look for a setText(String).
1504 If the expression returns an int, data binding will search for a setText(int)
1505 method. Be careful to have the expression return the correct type, casting if
1506 necessary. Note that data binding will work even if no attribute exists with
1507 the given name. You can then easily "create" attributes for any setter by
Mark Lu011c07b2016-07-28 11:15:11 -07001508 using data binding. For example, support DrawerLayout doesn't have any
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001509 attributes, but plenty of setters. You can use the automatic setters to use
1510 one of these.
1511</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001512
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001513<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001514&lt;android.support.v4.widget.<strong>DrawerLayout
1515 android:layout_width="wrap_content"
1516 android:layout_height="wrap_content"
1517 app:scrimColor="&commat;{&commat;color/scrim}"
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001518 app:drawerListener="&commat;{fragment.drawerListener}"/&gt;</strong>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001519</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001520<h3 id="renamed_setters">
1521 Renamed Setters
1522</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001523
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001524<p>
Mark Lu011c07b2016-07-28 11:15:11 -07001525 Some attributes have setters that don't match by name. For these
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001526 methods, an attribute may be associated with the setter through
George Mount4ba18202015-07-27 12:39:28 -07001527 {@link android.databinding.BindingMethods} annotation. This must be associated with
1528 a class and contains {@link android.databinding.BindingMethod} annotations, one for
1529 each renamed method. For example, the <strong><code>android:tint</code></strong> attribute
1530 is really associated with {@link android.widget.ImageView#setImageTintList}, not
1531 <code>setTint</code>.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001532</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001533
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001534<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001535&commat;BindingMethods({
George Mount4ba18202015-07-27 12:39:28 -07001536 &commat;BindingMethod(type = "android.widget.ImageView",
1537 attribute = "android:tint",
1538 method = "setImageTintList"),
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001539})
1540</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001541<p>
1542 It is unlikely that developers will need to rename setters; the android
1543 framework attributes have already been implemented.
1544</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001545
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001546<h3 id="custom_setters">
1547 Custom Setters
1548</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001549
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001550<p>
1551 Some attributes need custom binding logic. For example, there is no
1552 associated setter for the <strong><code>android:paddingLeft</code></strong>
1553 attribute. Instead, <code>setPadding(left, top, right, bottom)</code> exists.
George Mount4ba18202015-07-27 12:39:28 -07001554 A static binding adapter method with the {@link android.databinding.BindingAdapter}
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001555 annotation allows the developer to customize how a setter for an attribute is
1556 called.
1557</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001558
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001559<p>
1560 The android attributes have already had <code>BindingAdapter</code>s created.
1561 For example, here is the one for <code>paddingLeft</code>:
1562</p>
1563
1564<pre>
George Mount4ba18202015-07-27 12:39:28 -07001565&commat;BindingAdapter("android:paddingLeft")
1566public static void setPaddingLeft(View view, int padding) {
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001567 view.setPadding(padding,
1568 view.getPaddingTop(),
1569 view.getPaddingRight(),
1570 view.getPaddingBottom());
1571}
1572</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001573<p>
1574 Binding adapters are useful for other types of customization. For example, a
1575 custom loader can be called off-thread to load an image.
1576</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001577
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001578<p>
1579 Developer-created binding adapters will override the data binding default
1580 adapters when there is a conflict.
1581</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001582
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001583<p>
1584 You can also have adapters that receive multiple parameters.
1585</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001586
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001587<pre>
George Mount4ba18202015-07-27 12:39:28 -07001588&commat;BindingAdapter({"bind:imageUrl", "bind:error"})
1589public static void loadImage(ImageView view, String url, Drawable error) {
1590 Picasso.with(view.getContext()).load(url).error(error).into(view);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001591}
1592</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001593<pre>
Mark Lu011c07b2016-07-28 11:15:11 -07001594&lt;ImageView app:imageUrl="&commat;{venue.imageUrl}"
1595app:error="&commat;{&commat;drawable/venueError}"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001596</pre>
1597
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001598<p>
1599 This adapter will be called if both <strong>imageUrl</strong> and
1600 <strong>error</strong> are used for an ImageView and <em>imageUrl</em> is a
1601 string and <em>error</em> is a drawable.
1602</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001603
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001604<ul>
1605 <li>Custom namespaces are ignored during matching.
1606 </li>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001607
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001608 <li>You can also write adapters for android namespace.
1609 </li>
1610</ul>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001611
George Mount4ba18202015-07-27 12:39:28 -07001612<p>
1613 Binding adapter methods may optionally take the old values in their handlers. A method
1614 taking old and new values should have all old values for the attributes come first, followed
1615 by the new values:
1616</p>
1617<pre>
1618&commat;BindingAdapter("android:paddingLeft")
1619public static void setPaddingLeft(View view, int oldPadding, int newPadding) {
1620 if (oldPadding != newPadding) {
1621 view.setPadding(newPadding,
1622 view.getPaddingTop(),
1623 view.getPaddingRight(),
1624 view.getPaddingBottom());
1625 }
1626}
1627</pre>
1628<p>
1629 Event handlers may only be used with interfaces or abstract classes with one abstract method.
1630 For example:
1631</p>
1632<pre>
1633&commat;BindingAdapter("android:onLayoutChange")
1634public static void setOnLayoutChangeListener(View view, View.OnLayoutChangeListener oldValue,
1635 View.OnLayoutChangeListener newValue) {
1636 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
1637 if (oldValue != null) {
1638 view.removeOnLayoutChangeListener(oldValue);
1639 }
1640 if (newValue != null) {
1641 view.addOnLayoutChangeListener(newValue);
1642 }
1643 }
1644}
1645</pre>
1646<p>
1647 When a listener has multiple methods, it must be split into multiple listeners. For example,
1648 {@link android.view.View.OnAttachStateChangeListener} has two methods:
1649 {@link android.view.View.OnAttachStateChangeListener#onViewAttachedToWindow onViewAttachedToWindow()} and
1650 {@link android.view.View.OnAttachStateChangeListener#onViewDetachedFromWindow onViewDetachedFromWindow()}.
1651 We must then create two interfaces to differentiate the attributes and handlers for them.
1652</p>
1653
1654<pre>
1655&commat;TargetApi(VERSION_CODES.HONEYCOMB_MR1)
1656public interface OnViewDetachedFromWindow {
1657 void onViewDetachedFromWindow(View v);
1658}
1659
1660&commat;TargetApi(VERSION_CODES.HONEYCOMB_MR1)
1661public interface OnViewAttachedToWindow {
1662 void onViewAttachedToWindow(View v);
1663}
1664</pre>
1665<p>
1666 Because changing one listener will also affect the other, we must have three different
1667 binding adapters, one for each attribute and one for both, should they both be set.
1668</p>
1669<pre>
1670&commat;BindingAdapter("android:onViewAttachedToWindow")
1671public static void setListener(View view, OnViewAttachedToWindow attached) {
1672 setListener(view, null, attached);
1673}
1674
1675&commat;BindingAdapter("android:onViewDetachedFromWindow")
1676public static void setListener(View view, OnViewDetachedFromWindow detached) {
1677 setListener(view, detached, null);
1678}
1679
1680&commat;BindingAdapter({"android:onViewDetachedFromWindow", "android:onViewAttachedToWindow"})
1681public static void setListener(View view, final OnViewDetachedFromWindow detach,
1682 final OnViewAttachedToWindow attach) {
1683 if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) {
1684 final OnAttachStateChangeListener newListener;
1685 if (detach == null && attach == null) {
1686 newListener = null;
1687 } else {
1688 newListener = new OnAttachStateChangeListener() {
1689 &commat;Override
1690 public void onViewAttachedToWindow(View v) {
1691 if (attach != null) {
1692 attach.onViewAttachedToWindow(v);
1693 }
1694 }
1695
1696 &commat;Override
1697 public void onViewDetachedFromWindow(View v) {
1698 if (detach != null) {
1699 detach.onViewDetachedFromWindow(v);
1700 }
1701 }
1702 };
1703 }
1704 final OnAttachStateChangeListener oldListener = ListenerUtil.trackListener(view,
1705 newListener, R.id.onAttachStateChangeListener);
1706 if (oldListener != null) {
1707 view.removeOnAttachStateChangeListener(oldListener);
1708 }
1709 if (newListener != null) {
1710 view.addOnAttachStateChangeListener(newListener);
1711 }
1712 }
1713}
1714</pre>
1715<p>
1716 The above example is slightly more complicated than normal because View uses add and remove
1717 for the listener instead of a set method for {@link android.view.View.OnAttachStateChangeListener}.
1718 The <code>android.databinding.adapters.ListenerUtil</code> class helps keep track of the previous
1719 listeners so that they may be removed in the Binding Adaper.
1720</p>
1721<p>
1722 By annotating the interfaces <code>OnViewDetachedFromWindow</code> and
1723 <code>OnViewAttachedToWindow</code> with
1724 <code>&commat;TargetApi(VERSION_CODES.HONEYCOMB_MR1)</code>, the data binding code
1725 generator knows that the listener should only be generated when running on Honeycomb MR1
1726 and new devices, the same version supported by
1727 {@link android.view.View#addOnAttachStateChangeListener}.
1728</p>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001729<h2 id="converters">
1730 Converters
1731</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001732
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001733<h3 id="object_conversions">
1734 Object Conversions
1735</h3>
1736
1737<p>
1738 When an Object is returned from a binding expression, a setter will be chosen
1739 from the automatic, renamed, and custom setters. The Object will be cast to a
1740 parameter type of the chosen setter.
1741</p>
1742
1743<p>
1744 This is a convenience for those using ObservableMaps to hold data. for
1745 example:
1746</p>
1747
1748<pre>
George Mount4ba18202015-07-27 12:39:28 -07001749&lt;TextView
Mark Lu011c07b2016-07-28 11:15:11 -07001750 android:text='&commat;{userMap["lastName"]}'
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001751 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001752 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001753</pre>
1754
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001755<p>
1756The <code>userMap</code> returns an Object and that Object will be automatically cast to
1757 parameter type found in the setter <code>setText(CharSequence)</code>. When there
1758 may be confusion about the parameter type, the developer will need
1759 to cast in the expression.
1760</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001761
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001762<h3 id="custom_conversions">Custom Conversions</h3>
1763
1764<p>
1765 Sometimes conversions should be automatic between specific types. For
1766 example, when setting the background:
1767</p>
1768
1769<pre>
George Mount4ba18202015-07-27 12:39:28 -07001770&lt;View
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001771 android:background="&commat;{isError ? &commat;color/red : &commat;color/white}"
1772 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001773 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001774</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001775<p>
1776 Here, the background takes a <code>Drawable</code>, but the color is an
1777 integer. Whenever a <code>Drawable</code> is expected and an integer is
1778 returned, the <code>int</code> should be converted to a
1779 <code>ColorDrawable</code>. This conversion is done using a static method
1780 with a BindingConversion annotation:
1781</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001782
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001783<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001784&commat;BindingConversion
George Mount4ba18202015-07-27 12:39:28 -07001785public static ColorDrawable convertColorToDrawable(int color) {
1786 return new ColorDrawable(color);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001787}
1788</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001789<p>
1790 Note that conversions only happen at the setter level, so it is <strong>not
1791 allowed</strong> to mix types like this:
1792</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001793
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001794<pre>
George Mount4ba18202015-07-27 12:39:28 -07001795&lt;View
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001796 android:background="&commat;{isError ? &commat;drawable/error : &commat;color/white}"
1797 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001798 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001799</pre>
Daniel Yudaa41bb2015-12-08 10:58:07 -08001800
1801<h3 id="studio_support">Android Studio Support for Data Binding</h3>
1802
1803<p>
Cheryl Potter8dd7eea2016-04-04 17:10:06 -07001804Android Studio supports many of the code editing features for data binding code.
1805For example, it supports the following features for data binding expressions:</p>
1806<ul>
1807<li>Syntax highlighting</li>
1808<li>Flagging of expression language syntax errors</li>
1809<li>XML code completion</li>
1810<li>References, including <a class="external-link"
1811href="https://www.jetbrains.com/help/idea/2016.1/navigation-in-source-code.html?origin=old_help">
1812navigation</a> (such as navigate to a declaration) and
1813<a class="external-link"
1814href="https://www.jetbrains.com/help/idea/2016.1/viewing-inline-documentation.html?origin=old_help">
1815quick documentation</a></li>
1816</ul>
1817
1818<p class="note"><strong>Note:</strong> Arrays and a
1819<a href="https://docs.oracle.com/javase/tutorial/java/generics/types.html"
1820class="external-link">generic type</a>, such as the {@link
1821android.databinding.Observable} class, might display
1822errors when there are no errors.</p>
1823
Daniel Yudaa41bb2015-12-08 10:58:07 -08001824<p>
Cheryl Potter8dd7eea2016-04-04 17:10:06 -07001825The Preview pane displays default values for data binding expressions if
1826provided. In the following
1827example excerpt of an element from a layout XML file, the Preview pane displays
1828the {@code PLACEHOLDER} default text value in the <code>TextView</code>.
Daniel Yudaa41bb2015-12-08 10:58:07 -08001829</p>
1830
1831<pre>
1832&lt;TextView android:layout_width="wrap_content"
1833 android:layout_height="wrap_content"
1834 android:text="&commat;{user.firstName, default=PLACEHOLDER}"/&gt;
1835</pre>
1836
1837<p>
Cheryl Potter8dd7eea2016-04-04 17:10:06 -07001838If you need to display a default value during the design phase of your project,
1839you can also use tools attributes instead of default expression values, as
1840described in
1841<a class="external-link"
1842href="http://tools.android.com/tips/layout-designtime-attributes">
Daniel Yudaa41bb2015-12-08 10:58:07 -08001843Designtime Layout Attributes</a>.
Cheryl Potter8dd7eea2016-04-04 17:10:06 -07001844</p>
1845