blob: 8bbd833e1589e5aa6297b11cd9ddec24ff404e84 [file] [log] [blame]
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001page.title=Data Binding Guide
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07002page.tags="databinding", "layouts"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07003@jd:body
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07004
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07005<div id="qv-wrapper">
6 <div id="qv">
7 <h2>
8 In this document:
9 </h2>
10
11 <ol>
12 <li>
13 <a href="#build_environment">Build Environment</a>
14 </li>
15
16 <li>
17 <a href="#data_binding_layout_files">Data Binding Layout Files</a>
18 <ol>
19 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070020 <a href="#writing_expressions">Writing your first data binding
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070021 expressions</a>
22 </li>
23
24 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070025 <a href="#data_object">Data Object</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070026 </li>
27
28 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070029 <a href="#binding_data">Binding Data</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070030 </li>
George Mount4ba18202015-07-27 12:39:28 -070031
32 <li>
33 <a href="#binding_events">Binding Events</a>
34 </li>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070035 </ol>
36 </li>
37
38 <li>
39 <a href="#layout_details">Layout Details</a>
40 <ol>
41 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070042 <a href="#imports">Imports</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070043 </li>
44
45 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070046 <a href="#variables">Variables</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070047 </li>
48
49 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070050 <a href="#custom_binding_class_names">Custom Binding Class Names</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070051 </li>
52
53 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070054 <a href="#includes">Includes</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070055 </li>
56
57 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070058 <a href="#expression_language">Expression Language</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070059 </li>
60 </ol>
61 </li>
62
63 <li>
64 <a href="#data_objects">Data Objects</a>
65 <ol>
66 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070067 <a href="#observable_objects">Observable Objects</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070068 </li>
69
70 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070071 <a href="#observablefields">ObservableFields</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070072 </li>
73
74 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070075 <a href="#observable_collections">Observable Collections</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070076 </li>
77 </ol>
78 </li>
79
80 <li>
81 <a href="#generated_binding">Generated Binding</a>
82 <ol>
83 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070084 <a href="#creating">Creating</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070085 </li>
86
87 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070088 <a href="#views_with_ids">Views With IDs</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070089 </li>
90
91 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070092 <a href="#variables">Variables</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070093 </li>
94
95 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -070096 <a href="#viewstubs">ViewStubs</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -070097 </li>
98
99 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700100 <a href="#advanced_binding">Advanced Binding</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700101 </li>
102 </ol>
103 </li>
104
105 <li>
106 <a href="#attribute_setters">Attribute Setters</a>
107 <ol>
108 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700109 <a href="#automatic_setters">Automatic Setters</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700110 </li>
111
112 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700113 <a href="#renamed_setters">Renamed Setters</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700114 </li>
115
116 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700117 <a href="#custom_setters">Custom Setters</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700118 </li>
119 </ol>
120 </li>
121
122 <li>
123 <a href="#converters">Converters</a>
124 <ol>
125 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700126 <a href="#object_conversions">Object Conversions</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700127 </li>
128
129 <li>
Dirk Dougherty518651c2015-05-27 20:24:37 -0700130 <a href="#custom_conversions">Custom Conversions</a>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700131 </li>
132 </ol>
133 </li>
Daniel Yudaa41bb2015-12-08 10:58:07 -0800134
135 <li>
136 <a href="#studio_support">Android Studio Support for Data Binding</a>
137 </li>
138
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700139 </ol>
140 </div><!-- qv -->
141</div><!-- qv-wrapper -->
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700142
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700143<p>
144 This document explains how to use the Data Binding Library to write
145 declarative layouts and minimize the glue code necessary to bind your
146 application logic and layouts.
147</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700148
Claudio Cherubinob6e91df2015-08-21 14:49:09 -0700149<p>The Data Binding Library offers both flexibility and broad compatibility
Dirk Dougherty08710f12015-05-28 22:01:36 -0700150&mdash; it's a support library, so you can use it with all Android platform
151versions back to <strong>Android 2.1</strong> (API level 7+).</p>
152
sreevanis1a1d5db2015-10-30 14:44:51 -0700153<p>To use data binding, Android Plugin for Gradle <strong>1.5.0-alpha1</strong>
Dirk Doughertybcab1822015-06-02 14:05:31 -0700154or higher is required.</p>
Dirk Dougherty08710f12015-05-28 22:01:36 -0700155
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700156<h2 id="build_environment">
157 Build Environment
158</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700159
Dirk Dougherty08710f12015-05-28 22:01:36 -0700160<p>To get started with Data Binding, download the library from the Support
161repository in the Android SDK manager. </p>
162
sreevanis1a1d5db2015-10-30 14:44:51 -0700163<p>
164To configure your app to use data binding, add the <code>dataBinding</code> element to your
sreevanis0cd62032015-11-03 09:57:57 -0800165<code>build.gradle</code> file in the app module.
166</p>
167
168 <p>Use the following code snippet to configure data binding: </p>
sreevanis1a1d5db2015-10-30 14:44:51 -0700169
170<pre>
171android {
172 ....
173 dataBinding {
174 enabled = true
175 }
176}
177</pre>
Dirk Dougherty08710f12015-05-28 22:01:36 -0700178
sreevanis0cd62032015-11-03 09:57:57 -0800179<p>If you have an app module that depends on a library which uses data binding, your app module
180 must configure data binding in its <code>build.gradle</code> file as well.</p>
181
Dirk Doughertybcab1822015-06-02 14:05:31 -0700182<p>Also, make sure you are using a compatible version of Android Studio.
Daniel Yudaa41bb2015-12-08 10:58:07 -0800183<strong>Android Studio 1.3</strong> and later provides support for data binding as described in
184<a href="#studio_support">Android Studio Support for Data Binding</a>.
185</p>
Dirk Dougherty08710f12015-05-28 22:01:36 -0700186
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700187<h2 id="data_binding_layout_files">
188 Data Binding Layout Files
189</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700190
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700191<h3 id="writing_expressions">
192 Writing your first data binding expressions
193</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700194
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700195<p>
196 Data-binding layout files are slightly different and start with a root tag of
197 <strong>layout</strong> followed by a <strong>data</strong> element and a
198 <strong>view</strong> root element. This view element is what your root would
199 be in a non-binding layout file. A sample file looks like this:
200</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700201
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700202<pre>
George Mount4ba18202015-07-27 12:39:28 -0700203&lt;?xml version="1.0" encoding="utf-8"?&gt;
204&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"&gt;
205 &lt;data&gt;
206 &lt;variable name="user" type="com.example.User"/&gt;
207 &lt;/data&gt;
208 &lt;LinearLayout
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700209 android:orientation="vertical"
210 android:layout_width="match_parent"
George Mount4ba18202015-07-27 12:39:28 -0700211 android:layout_height="match_parent"&gt;
212 &lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700213 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700214 android:text="&commat;{user.firstName}"/&gt;
215 &lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700216 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700217 android:text="&commat;{user.lastName}"/&gt;
218 &lt;/LinearLayout&gt;
219&lt;/layout&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700220</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700221<p>
222 The user <strong>variable</strong> within <strong>data</strong> describes a
223 property that may be used within this layout.
224</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700225
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700226<pre>
227&lt;<strong>variable name="user" type="com.example.User"</strong>/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700228</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700229<p>
230 Expressions within the layout are written in the attribute properties using
231 the “<code>&commat;{}</code>” syntax. Here, the TextView’s text is set to the
232 firstName property of user:
233</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700234
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700235<pre>
George Mount4ba18202015-07-27 12:39:28 -0700236&lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700237 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700238 android:text="&commat;{user.firstName}"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700239</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700240<h3 id="data_object">
241 Data Object
242</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700243
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700244<p>
245 Let’s assume for now that you have a plain-old Java object (POJO) for User:
246</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700247
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700248<pre>
George Mount4ba18202015-07-27 12:39:28 -0700249public class User {
250 public final String firstName;
251 public final String lastName;
252 public User(String firstName, String lastName) {
253 this.firstName = firstName;
254 this.lastName = lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700255 }
256}
257</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700258<p>
259 This type of object has data that never changes. It is common in applications
260 to have data that is read once and never changes thereafter. It is also
261 possible to use a JavaBeans objects:
262</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700263
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700264<pre>
George Mount4ba18202015-07-27 12:39:28 -0700265public class User {
266 private final String firstName;
267 private final String lastName;
268 public User(String firstName, String lastName) {
269 this.firstName = firstName;
270 this.lastName = lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700271 }
George Mount4ba18202015-07-27 12:39:28 -0700272 public String getFirstName() {
273 return this.firstName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700274 }
George Mount4ba18202015-07-27 12:39:28 -0700275 public String getLastName() {
276 return this.lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700277 }
278}
279</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700280<p>
281 From the perspective of data binding, these two classes are equivalent. The
282 expression <strong><code>&commat;{user.firstName}</code></strong> used for
283 the TextView’s <strong><code>android:text</code></strong> attribute will
284 access the <strong><code>firstName</code></strong> field in the former class
George Mount4ba18202015-07-27 12:39:28 -0700285 and the <code>getFirstName()</code> method in the latter class. Alternatively, it
286 will also be resolved to <code>firstName()</code> if that method exists.
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700287</p>
288
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700289<h3 id="binding_data">
290 Binding Data
291</h3>
292
293<p>
294 By default, a Binding class will be generated based on the name of the layout
295 file, converting it to Pascal case and suffixing “Binding” to it. The above
George Mount4ba18202015-07-27 12:39:28 -0700296 layout file was <code>main_activity.xml</code> so the generate class was
297 <code>MainActivityBinding</code>. This class holds all the bindings from the
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700298 layout properties (e.g. the <code>user</code> variable) to the layout’s Views
299 and knows how to assign values for the binding expressions.The easiest means
300 for creating the bindings is to do it while inflating:
301</p>
302
303<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700304&commat;Override
George Mount4ba18202015-07-27 12:39:28 -0700305protected void onCreate(Bundle savedInstanceState) {
306 super.onCreate(savedInstanceState);
307 MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
308 User user = new User("Test", "User");
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700309 binding.setUser(user);
310}
311</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700312<p>
313 You’re done! Run the application and you’ll see Test User in the UI.
314 Alternatively, you can get the view via:
315</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700316
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700317<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700318MainActivityBinding binding = MainActivityBinding.<em>inflate</em>(getLayoutInflater());
319</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700320<p>
321 If you are using data binding items inside a ListView or RecyclerView
322 adapter, you may prefer to use:
323</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700324
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700325<pre>
George Mount4ba18202015-07-27 12:39:28 -0700326ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700327//or
328ListItemBinding binding = DataBindingUtil.<em>inflate</em>(layoutInflater, R.layout.<em><strong>list_item</strong></em>, viewGroup, <strong>false</strong>);
329</pre>
George Mount4ba18202015-07-27 12:39:28 -0700330
331<h3 id="binding_events">
332 Binding Events
333</h3>
334<p>
335 Events may be bound to handler methods directly, similar to the way
336 <strong><code>android:onClick</code></strong> can be assigned to a method in the Activity.
337 Event attribute names are governed by the name of the listener method with a few exceptions.
338 For example, {@link android.view.View.OnLongClickListener} has a method {@link android.view.View.OnLongClickListener#onLongClick onLongClick()},
339 so the attribute for this event is <code>android:onLongClick</code>.
340</p>
341<p>
342 To assign an event to its handler, use a normal binding expression, with the value
343 being the method name to call. For example, if your data object has two methods:
344</p>
345<pre>public class MyHandlers {
346 public void onClickFriend(View view) { ... }
347 public void onClickEnemy(View view) { ... }
348}
349</pre>
350<p>
351 The binding expression can assign the click listener for a View:
352</p>
353<pre>
354&lt;?xml version="1.0" encoding="utf-8"?&gt;
355&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"&gt;
356 &lt;data&gt;
357 &lt;variable name="handlers" type="com.example.Handlers"/&gt;
358 &lt;variable name="user" type="com.example.User"/&gt;
359 &lt;/data&gt;
360 &lt;LinearLayout
361 android:orientation="vertical"
362 android:layout_width="match_parent"
363 android:layout_height="match_parent"&gt;
364 &lt;TextView android:layout_width="wrap_content"
365 android:layout_height="wrap_content"
366 android:text="&commat;{user.firstName}"
367 android:onClick="&commat;{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/&gt;
368 &lt;TextView android:layout_width="wrap_content"
369 android:layout_height="wrap_content"
370 android:text="&commat;{user.lastName}"
371 android:onClick="&commat;{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/&gt;
372 &lt;/LinearLayout&gt;
373&lt;/layout&gt;
374</pre>
George Mount9b332f32016-01-28 14:31:25 -0800375
376<p>
377 Some specialized click event handlers exist and they need an attribute other than
378 <code>android:onClick</code> to avoid a conflict. The following attributes have been created
379 to avoid such conflicts:
380</p>
381
382<table>
383 <tr>
384 <th>Class</th>
385 <th>Listener Setter</th>
386 <th>Attribute</th>
387 </tr>
388 <tr>
389 <td>{@link android.widget.SearchView}</td>
390 <td>{@link android.widget.SearchView#setOnSearchClickListener}</td>
391 <td><code>android:onSearchClick</code></td>
392 </tr>
393 <tr>
394 <td>{@link android.widget.ZoomControls}</td>
395 <td>{@link android.widget.ZoomControls#setOnZoomInClickListener}</td>
396 <td><code>android:onZoomIn</code></td>
397 </tr>
398 <tr>
399 <td>{@link android.widget.ZoomControls}</td>
400 <td>{@link android.widget.ZoomControls#setOnZoomOutClickListener}</td>
401 <td><code>android:onZoomOut</code></td>
402 </tr>
403</table>
404
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700405<h2 id="layout_details">
406 Layout Details
407</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700408
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700409<h3 id="imports">
410 Imports
411</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700412
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700413<p>
414 Zero or more <strong><code>import</code></strong> elements may be used inside
415 the <strong><code>data</code></strong> element. These allow easy reference to
416 classes inside your layout file, just like in Java.
417</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700418
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700419<pre>
George Mount4ba18202015-07-27 12:39:28 -0700420&lt;data&gt;
421 &lt;import type="android.view.View"/&gt;
422&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700423</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700424<p>
425 Now, View may be used within your binding expression:
426</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700427
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700428<pre>
George Mount4ba18202015-07-27 12:39:28 -0700429&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700430 android:text="&commat;{user.lastName}"
431 android:layout_width="wrap_content"
432 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700433 android:visibility="&commat;{user.isAdult ? View.VISIBLE : View.GONE}"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700434</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700435<p>
436 When there are class name conflicts, one of the classes may be renamed to an
437 “alias:”
438</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700439
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700440<pre>
George Mount4ba18202015-07-27 12:39:28 -0700441&lt;import type="android.view.View"/&gt;
442&lt;import type="com.example.real.estate.View"
443 alias="Vista"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700444</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700445<p>
446 Now, <strong><code>Vista</code></strong> may be used to reference the
447 <code>com.example.real.estate.View</code> and
448 <strong><code>View</code></strong> may be used to reference
449 <code>android.view.View</code> within the layout file. Imported types may be
450 used as type references in variables and expressions:
451</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700452
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700453<pre>
George Mount4ba18202015-07-27 12:39:28 -0700454&lt;data&gt;
455 &lt;import type="com.example.User"/&gt;
456 &lt;import type="java.util.List"/&gt;
457 &lt;variable name="user" type="User"/&gt;
458 &lt;variable name="userList" type="List&amp;lt;User&gt;"/&gt;
459&lt;/data&gt;
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700460</pre>
Dirk Dougherty08710f12015-05-28 22:01:36 -0700461<p class="caution">
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700462 <strong>Note</strong>: Android Studio does not yet handle imports so the
463 autocomplete for imported variables may not work in your IDE. Your
464 application will still compile fine and you can work around the IDE issue by
465 using fully qualified names in your variable definitions.
466</p>
467
468<pre>
George Mount4ba18202015-07-27 12:39:28 -0700469&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700470 android:text="&commat;{((User)(user.connection)).lastName}"
471 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700472 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700473</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700474<p>
475 Imported types may also be used when referencing static fields and methods in
476 expressions:
477</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700478
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700479<pre>
George Mount4ba18202015-07-27 12:39:28 -0700480&lt;data&gt;
481 &lt;import type="com.example.MyStringUtils"/&gt;
482 &lt;variable name="user" type="com.example.User"/&gt;
483&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700484
George Mount4ba18202015-07-27 12:39:28 -0700485&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700486 android:text="&commat;{MyStringUtils.capitalize(user.lastName)}"
487 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700488 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700489</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700490<p>
491 Just as in Java, <code>java.lang.*</code> is imported automatically.
492</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700493
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700494<h3 id="variables">
495 Variables
496</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700497
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700498<p>
499 Any number of <strong><code>variable</code></strong> elements may be used
500 inside the <strong><code>data</code></strong> element. Each
501 <strong><code>variable</code></strong> element describes a property that may
502 be set on the layout to be used in binding expressions within the layout
503 file.
504</p>
505
506<pre>
George Mount4ba18202015-07-27 12:39:28 -0700507&lt;data&gt;
508 &lt;import type="android.graphics.drawable.Drawable"/&gt;
509 &lt;variable name="user" type="com.example.User"/&gt;
510 &lt;variable name="image" type="Drawable"/&gt;
511 &lt;variable name="note" type="String"/&gt;
512&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700513</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700514<p>
515 The variable types are inspected at compile time, so if a variable implements
George Mount4ba18202015-07-27 12:39:28 -0700516 {@link android.databinding.Observable} or is an <a href=
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700517 "#observable_collections">observable collection</a>, that should be reflected
518 in the type. If the variable is a base class or interface that does not
519 implement the Observable* interface, the variables will <strong>not
520 be</strong> observed!
521</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700522
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700523<p>
524 When there are different layout files for various configurations (e.g.
525 landscape or portrait), the variables will be combined. There must not be
526 conflicting variable definitions between these layout files.
527</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700528
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700529<p>
530 The generated binding class will have a setter and getter for each of the
531 described variables. The variables will take the default Java values until
532 the setter is called &mdash; <code>null</code> for reference types,
533 <code>0</code> for <code>int</code>, <code>false</code> for
534 <code>boolean</code>, etc.
535</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700536
George Mount9b332f32016-01-28 14:31:25 -0800537<p>
538 A special variable named <code>context</code> is generated for use in binding
539 expressions as needed. The value for <code>context</code> is the
540 <code>Context</code> from the root View's {@link android.view.View#getContext}.
541 The <code>context</code> variable will be overridden by an explicit variable
542 declaration with that name.
543</p>
544
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700545<h3 id="custom_binding_class_names">
546 Custom Binding Class Names
547</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700548
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700549<p>
550 By default, a Binding class is generated based on the name of the layout
551 file, starting it with upper-case, removing underscores ( _ ) and
552 capitalizing the following letter and then suffixing “Binding”. This class
553 will be placed in a databinding package under the module package. For
554 example, the layout file <code>contact_item.xml</code> will generate
555 <code>ContactItemBinding</code>. If the module package is
556 <code>com.example.my.app</code>, then it will be placed in
557 <code>com.example.my.app.databinding</code>.
558</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700559
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700560<p>
561 Binding classes may be renamed or placed in different packages by adjusting
562 the <strong><code>class</code></strong> attribute of the
563 <strong><code>data</code></strong> element. For example:
564</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700565
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700566<pre>
George Mount4ba18202015-07-27 12:39:28 -0700567&lt;data class="ContactItem"&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700568 ...
George Mount4ba18202015-07-27 12:39:28 -0700569&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700570</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700571<p>
572 This generates the binding class as <code>ContactItem</code> in the
573 databinding package in the module package. If the class should be generated
574 in a different package within the module package, it may be prefixed with
575 “.”:
576</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700577
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700578<pre>
George Mount4ba18202015-07-27 12:39:28 -0700579&lt;data class=".ContactItem"&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700580 ...
George Mount4ba18202015-07-27 12:39:28 -0700581&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700582</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700583<p>
584 In this case, <code>ContactItem</code> is generated in the module package
585 directly. Any package may be used if the full package is provided:
586</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700587
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700588<pre>
George Mount4ba18202015-07-27 12:39:28 -0700589&lt;data class="com.example.ContactItem"&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700590 ...
George Mount4ba18202015-07-27 12:39:28 -0700591&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700592</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700593<h3 id="includes">
594 Includes
595</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700596
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700597<p>
598 Variables may be passed into an included layout&apos;s binding from the
599 containing layout by using the application namespace and the variable name in
600 an attribute:
601</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700602
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700603<pre>
George Mount4ba18202015-07-27 12:39:28 -0700604&lt;?xml version="1.0" encoding="utf-8"?&gt;
605&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"
606 xmlns:bind="http://schemas.android.com/apk/res-auto"&gt;
607 &lt;data&gt;
608 &lt;variable name="user" type="com.example.User"/&gt;
609 &lt;/data&gt;
610 &lt;LinearLayout
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700611 android:orientation="vertical"
612 android:layout_width="match_parent"
George Mount4ba18202015-07-27 12:39:28 -0700613 android:layout_height="match_parent"&gt;
614 &lt;include layout="&commat;layout/name"
615 bind:user="&commat;{user}"/&gt;
616 &lt;include layout="&commat;layout/contact"
617 bind:user="&commat;{user}"/&gt;
618 &lt;/LinearLayout&gt;
619&lt;/layout&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700620</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700621<p>
622 Here, there must be a <code>user</code> variable in both the
623 <code>name.xml</code> and <code>contact.xml</code> layout files.
624</p>
George Mount4ba18202015-07-27 12:39:28 -0700625<p>
626 Data binding does not support include as a direct child of a merge element. For example,
627 <strong>the following layout is not supported:</strong>
628</p>
629<pre>
630&lt;?xml version="1.0" encoding="utf-8"?&gt;
631&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"
632 xmlns:bind="http://schemas.android.com/apk/res-auto"&gt;
633 &lt;data&gt;
634 &lt;variable name="user" type="com.example.User"/&gt;
635 &lt;/data&gt;
636 &lt;merge&gt;
637 &lt;include layout="&commat;layout/name"
638 bind:user="&commat;{user}"/&gt;
639 &lt;include layout="&commat;layout/contact"
640 bind:user="&commat;{user}"/&gt;
641 &lt;/merge&gt;
642&lt;/layout&gt;
643</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700644<h3 id="expression_language">
645 Expression Language
646</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700647
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700648<h4 id="common_features">
649 Common Features
650</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700651
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700652<p>
653 The expression language looks a lot like a Java expression. These are the
654 same:
655</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700656
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700657<ul>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700658 <li>Mathematical <strong><code>+ - / * %</code></strong>
659 </li>
660
661 <li>String concatenation <strong><code>+</code></strong>
662 </li>
663
664 <li>
George Mount4ba18202015-07-27 12:39:28 -0700665 Logical <strong><code>&& ||</code></strong>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700666 </li>
667
George Mount4ba18202015-07-27 12:39:28 -0700668 <li>Binary <strong><code>& | ^</code></strong>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700669 </li>
670
671 <li>Unary <strong><code>+ - ! ~</code></strong>
672 </li>
673
674 <li>Shift <strong><code>&gt;&gt; &gt;&gt;&gt; &lt;&lt;</code></strong>
675 </li>
676
677 <li>Comparison <strong><code>== &gt; &lt; &gt;= &lt;=</code></strong>
678 </li>
679
680 <li>
681 <strong><code>instanceof</code></strong>
682 </li>
683
684 <li>Grouping <strong><code>()</code></strong>
685 </li>
686
687 <li>Literals - character, String, numeric, <strong><code>null</code></strong>
688 </li>
689
690 <li>Cast
691 </li>
692
693 <li>Method calls
694 </li>
695
696 <li>Field access
697 </li>
698
699 <li>Array access <strong><code>[]</code></strong>
700 </li>
701
702 <li>Ternary operator <strong><code>?:</code></strong>
703 </li>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700704</ul>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700705
706<p>
707 Examples:
708</p>
709
710<pre>
George Mount4ba18202015-07-27 12:39:28 -0700711android:text="&commat;{String.valueOf(index + 1)}"
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700712android:visibility="&commat;{age &amp;lt; 13 ? View.GONE : View.VISIBLE}"
George Mount4ba18202015-07-27 12:39:28 -0700713android:transitionName=&apos;&commat;{"image_" + id}&apos;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700714</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700715<h4 id="missing_operations">
716 Missing Operations
717</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700718
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700719<p>
720 A few operations are missing from the expression syntax that you can use in
721 Java.
722</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700723
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700724<ul>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700725 <li>
726 <strong><code>this</code></strong>
727 </li>
728
729 <li>
730 <strong><code>super</code></strong>
731 </li>
732
733 <li>
734 <strong><code>new</code></strong>
735 </li>
736
737 <li>Explicit generic invocation
738 </li>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700739</ul>
740
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700741<h4 id="null_coalescing_operator">
742 Null Coalescing Operator
743</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700744
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700745<p>
746 The null coalescing operator (<strong><code>??</code></strong>) chooses the
747 left operand if it is not null or the right if it is null.
748</p>
749
750<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700751<strong>android:text="&commat;{user.displayName ?? user.lastName}"</strong>
752</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700753<p>
754 This is functionally equivalent to:
755</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700756
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700757<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700758<strong>android:text="&commat;{user.displayName != null ? user.displayName : user.lastName}"</strong>
759</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700760<h4 id="property_reference">
761 Property Reference
762</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700763
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700764<p>
765 The first was already discussed in the <a href=
766 "#writing_your_first_data_binding_expressions">Writing your first data
767 binding expressions</a> above: short form JavaBean references. When an
768 expression references a property on a class, it uses the same format for
769 fields, getters, and ObservableFields.
770</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700771
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700772<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700773<strong>android:text="&commat;{user.lastName}"</strong>
774</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700775<h4>
776 Avoiding NullPointerException
777</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700778
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700779<p>
780 Generated data binding code automatically checks for nulls and avoid null
781 pointer exceptions. For example, in the expression
782 <code>&commat;{user.name}</code>, if <code>user</code> is null,
783 <code>user.name</code> will be assigned its default value (null). If you were
784 referencing <code>user.age</code>, where age is an <code>int</code>, then it
785 would default to 0.
786</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700787
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700788<h4 id="collections">
789 Collections
790</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700791
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700792<p>
793 Common collections: arrays, lists, sparse lists, and maps, may be accessed
794 using the <code>[]</code> operator for convenience.
795</p>
796
797<pre>
George Mount4ba18202015-07-27 12:39:28 -0700798&lt;data&gt;
799 &lt;import type="android.util.SparseArray"/&gt;
800 &lt;import type="java.util.Map"/&gt;
801 &lt;import type="java.util.List"/&gt;
802 &lt;variable name="list" type="List&amp;lt;String&gt;"/&gt;
803 &lt;variable name="sparse" type="SparseArray&amp;lt;String&gt;"/&gt;
804 &lt;variable name="map" type="Map&amp;lt;String, String&gt;"/&gt;
805 &lt;variable name="index" type="int"/&gt;
806 &lt;variable name="key" type="String"/&gt;
807&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700808
George Mount4ba18202015-07-27 12:39:28 -0700809android:text="&commat;{list[index]}"
810
811android:text="&commat;{sparse[index]}"
812
813android:text="&commat;{map[key]}"
814
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700815</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700816<h4 id="string_literals">
817 String Literals
818</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700819
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700820<p>
821 When using single quotes around the attribute value, it is easy to use double
822 quotes in the expression:
823</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700824
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700825<pre>
George Mount4ba18202015-07-27 12:39:28 -0700826android:text=&apos;&commat;{map["firstName"]}&apos;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700827</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700828<p>
829 It is also possible to use double quotes to surround the attribute value.
830 When doing so, String literals should either use the &amp;quot; or back quote
831 (`).
832</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700833
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700834<pre>
George Mount4ba18202015-07-27 12:39:28 -0700835android:text="&commat;{map[`firstName`}"
836android:text="&commat;{map[&amp;quot;firstName&amp;quot;]}"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700837</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700838<h4 id="resources">
839 Resources
840</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700841
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700842<p>
843 It is possible to access resources as part of expressions using the normal
844 syntax:
845</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700846
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700847<pre>
George Mount4ba18202015-07-27 12:39:28 -0700848android:padding="&commat;{large? &commat;dimen/largePadding : &commat;dimen/smallPadding}"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700849</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700850<p>
851 Format strings and plurals may be evaluated by providing parameters:
852</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700853
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700854<pre>
George Mount4ba18202015-07-27 12:39:28 -0700855android:text="&commat;{&commat;string/nameFormat(firstName, lastName)}"
856android:text="&commat;{&commat;plurals/banana(bananaCount)}"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700857</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700858<p>
859 When a plural takes multiple parameters, all parameters should be passed:
860</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700861
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700862<pre>
863
864 Have an orange
865 Have %d oranges
866
George Mount4ba18202015-07-27 12:39:28 -0700867android:text="&commat;{&commat;plurals/orange(orangeCount, orangeCount)}"
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700868</pre>
869<p>
870 Some resources require explicit type evaluation.
871</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700872
873<table>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700874 <tr>
875 <th>
876 Type
877 </th>
878 <th>
879 Normal Reference
880 </th>
881 <th>
882 Expression Reference
883 </th>
884 </tr>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700885
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700886 <tr>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700887 <td>
George Mount4ba18202015-07-27 12:39:28 -0700888 String[]
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700889 </td>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700890 <td>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700891 &commat;array
892 </td>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700893 <td>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700894 &commat;stringArray
895 </td>
896 </tr>
897
898 <tr>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700899 <td>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700900 int[]
901 </td>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700902 <td>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700903 &commat;array
904 </td>
905 <td>
906 &commat;intArray
907 </td>
908 </tr>
909
910 <tr>
911 <td>
912 TypedArray
913 </td>
914 <td>
915 &commat;array
916 </td>
917 <td>
918 &commat;typedArray
919 </td>
920 </tr>
921
922 <tr>
923 <td>
924 Animator
925 </td>
926 <td>
927 &commat;animator
928 </td>
929 <td>
930 &commat;animator
931 </td>
932 </tr>
933
934 <tr>
935 <td>
936 StateListAnimator
937 </td>
938 <td>
939 &commat;animator
940 </td>
941 <td>
942 &commat;stateListAnimator
943 </td>
944 </tr>
945
946 <tr>
947 <td>
948 color <code>int</code>
949 </td>
950 <td>
George Mount4ba18202015-07-27 12:39:28 -0700951 &commat;color
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700952 </td>
953 <td>
954 &commat;color
955 </td>
956 </tr>
957
958 <tr>
959 <td>
960 ColorStateList
961 </td>
962 <td>
963 &commat;color
964 </td>
965 <td>
966 &commat;colorStateList
967 </td>
968 </tr>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700969</table>
970
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700971<h2 id="data_objects">
972 Data Objects
973</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700974
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700975<p>
976 Any plain old Java object (POJO) may be used for data binding, but modifying
977 a POJO will not cause the UI to update. The real power of data binding can be
978 used by giving your data objects the ability to notify when data changes.
979 There are three different data change notification mechanisms,
George Mount4ba18202015-07-27 12:39:28 -0700980 <a href="#observable_objects">Observable objects</a>,
981 <a href="#observablefields">observable fields</a>, and
982 <a href="#observable_collections">observable collection</a>s.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700983</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700984
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700985<p>
986 When one of these observable data object is bound to the UI and a property of
987 the data object changes, the UI will be updated automatically.
988</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700989
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700990<h3 id="observable_objects">
991 Observable Objects
992</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700993
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700994<p>
George Mount4ba18202015-07-27 12:39:28 -0700995 A class implementing the {@link android.databinding.Observable} interface
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700996 will allow the binding to attach a single listener to a bound object to
997 listen for changes of all properties on that object.
998</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700999
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001000<p>
George Mount4ba18202015-07-27 12:39:28 -07001001 The {@link android.databinding.Observable} interface has a mechanism to add and remove
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001002 listeners, but notifying is up to the developer. To make development easier,
George Mount4ba18202015-07-27 12:39:28 -07001003 a base class, {@link android.databinding.BaseObservable}, was created to implement the
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001004 listener registration mechanism. The data class implementer is still
1005 responsible for notifying when the properties change. This is done by
George Mount4ba18202015-07-27 12:39:28 -07001006 assigning a {@link android.databinding.Bindable} annotation to the getter and notifying in
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001007 the setter.
1008</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001009
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001010<pre>
George Mount4ba18202015-07-27 12:39:28 -07001011private static class User extends BaseObservable {
1012 private String firstName;
1013 private String lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001014 &commat;Bindable
George Mount4ba18202015-07-27 12:39:28 -07001015 public String getFirstName() {
1016 return this.firstName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001017 }
1018 &commat;Bindable
George Mount4ba18202015-07-27 12:39:28 -07001019 public String getLastName() {
1020 return this.lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001021 }
George Mount4ba18202015-07-27 12:39:28 -07001022 public void setFirstName(String firstName) {
1023 this.firstName = firstName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001024 notifyPropertyChanged(BR.firstName);
1025 }
George Mount4ba18202015-07-27 12:39:28 -07001026 public void setLastName(String lastName) {
1027 this.lastName = lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001028 notifyPropertyChanged(BR.lastName);
1029 }
1030}
1031</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001032<p>
George Mount4ba18202015-07-27 12:39:28 -07001033 The {@link android.databinding.Bindable} annotation generates an entry in the BR class file
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001034 during compilation. The BR class file will be generated in the module
George Mount4ba18202015-07-27 12:39:28 -07001035 package. If the base class for data classes cannot be changed, the
1036 {@link android.databinding.Observable} interface may be implemented using the convenient
1037 {@link android.databinding.PropertyChangeRegistry} to store and notify listeners
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001038 efficiently.
1039</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001040
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001041<h3 id="observablefields">
1042 ObservableFields
1043</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001044
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001045<p>
George Mount4ba18202015-07-27 12:39:28 -07001046 A little work is involved in creating {@link android.databinding.Observable} classes, so
1047 developers who want to save time or have few properties may use
1048 {@link android.databinding.ObservableField} and its siblings
1049 {@link android.databinding.ObservableBoolean},
1050 {@link android.databinding.ObservableByte},
1051 {@link android.databinding.ObservableChar},
1052 {@link android.databinding.ObservableShort},
1053 {@link android.databinding.ObservableInt},
1054 {@link android.databinding.ObservableLong},
1055 {@link android.databinding.ObservableFloat},
1056 {@link android.databinding.ObservableDouble}, and
1057 {@link android.databinding.ObservableParcelable}.
1058 <code>ObservableFields</code> are self-contained observable objects that have a single
1059 field. The primitive versions avoid boxing and unboxing during access operations.
1060 To use, create a public final field in the data class:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001061</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001062
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001063<pre>
George Mount4ba18202015-07-27 12:39:28 -07001064private static class User {
1065 public final ObservableField&lt;String&gt; firstName =
1066 new ObservableField&lt;&gt;();
1067 public final ObservableField&lt;String&gt; lastName =
1068 new ObservableField&lt;&gt;();
1069 public final ObservableInt age = new ObservableInt();
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001070}
1071</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001072<p>
1073 That&apos;s it! To access the value, use the set and get accessor methods:
1074</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001075
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001076<pre>
George Mount4ba18202015-07-27 12:39:28 -07001077user.firstName.set("Google");
1078int age = user.age.get();
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001079</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001080<h3 id="observable_collections">
1081 Observable Collections
1082</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001083
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001084<p>
1085 Some applications use more dynamic structures to hold data. Observable
George Mount4ba18202015-07-27 12:39:28 -07001086 collections allow keyed access to these data objects.
1087 {@link android.databinding.ObservableArrayMap} is
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001088 useful when the key is a reference type, such as String.
1089</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001090
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001091<pre>
George Mount4ba18202015-07-27 12:39:28 -07001092ObservableArrayMap&lt;String, Object&gt; user = new ObservableArrayMap&lt;&gt;();
1093user.put("firstName", "Google");
1094user.put("lastName", "Inc.");
1095user.put("age", 17);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001096</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001097<p>
1098 In the layout, the map may be accessed through the String keys:
1099</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001100
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001101<pre>
George Mount4ba18202015-07-27 12:39:28 -07001102&lt;data&gt;
1103 &lt;import type="android.databinding.ObservableMap"/&gt;
1104 &lt;variable name="user" type="ObservableMap&amp;lt;String, Object&gt;"/&gt;
1105&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001106
George Mount4ba18202015-07-27 12:39:28 -07001107&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001108 android:text=&apos;&commat;{user["lastName"]}&apos;
1109 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001110 android:layout_height="wrap_content"/&gt;
1111&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001112 android:text=&apos;&commat;{String.valueOf(1 + (Integer)user["age"])}&apos;
1113 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001114 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001115</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001116<p>
George Mount4ba18202015-07-27 12:39:28 -07001117 {@link android.databinding.ObservableArrayList} is useful when the key is an integer:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001118</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001119
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001120<pre>
George Mount4ba18202015-07-27 12:39:28 -07001121ObservableArrayList&lt;Object&gt; user = new ObservableArrayList&lt;&gt;();
1122user.add("Google");
1123user.add("Inc.");
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001124user.add(17);
1125</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001126<p>
1127 In the layout, the list may be accessed through the indices:
1128</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001129
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001130<pre>
George Mount4ba18202015-07-27 12:39:28 -07001131&lt;data&gt;
1132 &lt;import type="android.databinding.ObservableList"/&gt;
1133 &lt;import type="com.example.my.app.Fields"/&gt;
1134 &lt;variable name="user" type="ObservableList&amp;lt;Object&gt;"/&gt;
1135&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001136
George Mount4ba18202015-07-27 12:39:28 -07001137&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001138 android:text=&apos;&commat;{user[Fields.LAST_NAME]}&apos;
1139 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001140 android:layout_height="wrap_content"/&gt;
1141&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001142 android:text=&apos;&commat;{String.valueOf(1 + (Integer)user[Fields.AGE])}&apos;
1143 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001144 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001145</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001146<h2 id="generated_binding">
1147 Generated Binding
1148</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001149
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001150<p>
1151 The generated binding class links the layout variables with the Views within
1152 the layout. As discussed earlier, the name and package of the Binding may be
1153 <a href="#custom_binding_class_names">customized</a>. The Generated binding
George Mount4ba18202015-07-27 12:39:28 -07001154 classes all extend {@link android.databinding.ViewDataBinding}.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001155</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001156
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001157<h3 id="creating">
1158 Creating
1159</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001160
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001161<p>
1162 The binding should be created soon after inflation to ensure that the View
1163 hierarchy is not disturbed prior to binding to the Views with expressions
1164 within the layout. There are a few ways to bind to a layout. The most common
1165 is to use the static methods on the Binding class.The inflate method inflates
1166 the View hierarchy and binds to it all it one step. There is a simpler
George Mount4ba18202015-07-27 12:39:28 -07001167 version that only takes a {@link android.view.LayoutInflater} and one that takes a
1168 {@link android.view.ViewGroup} as well:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001169</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001170
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001171<pre>
George Mount4ba18202015-07-27 12:39:28 -07001172MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater);
1173MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001174</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001175<p>
1176 If the layout was inflated using a different mechanism, it may be bound
1177 separately:
1178</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001179
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001180<pre>
George Mount4ba18202015-07-27 12:39:28 -07001181MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001182</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001183<p>
1184 Sometimes the binding cannot be known in advance. In such cases, the binding
George Mount4ba18202015-07-27 12:39:28 -07001185 can be created using the {@link android.databinding.DataBindingUtil} class:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001186</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001187
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001188<pre>
George Mount4ba18202015-07-27 12:39:28 -07001189ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId,
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001190 parent, attachToParent);
George Mount4ba18202015-07-27 12:39:28 -07001191ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001192</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001193<h3 id="views_with_ids">
1194 Views With IDs
1195</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001196
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001197<p>
1198 A public final field will be generated for each View with an ID in the
1199 layout. The binding does a single pass on the View hierarchy, extracting the
1200 Views with IDs. This mechanism can be faster than calling findViewById for
1201 several Views. For example:
1202</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001203
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001204<pre>
George Mount4ba18202015-07-27 12:39:28 -07001205&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"&gt;
1206 &lt;data&gt;
1207 &lt;variable name="user" type="com.example.User"/&gt;
1208 &lt;/data&gt;
1209 &lt;LinearLayout
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001210 android:orientation="vertical"
1211 android:layout_width="match_parent"
George Mount4ba18202015-07-27 12:39:28 -07001212 android:layout_height="match_parent"&gt;
1213 &lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001214 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001215 android:text="&commat;{user.firstName}"
1216 android:id="&commat;+id/firstName"/&gt;
1217 &lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001218 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001219 android:text="&commat;{user.lastName}"
1220 android:id="&commat;+id/lastName"/&gt;
1221 &lt;/LinearLayout&gt;
1222&lt;/layout&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001223</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001224<p>
1225 Will generate a binding class with:
1226</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001227
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001228<pre>
George Mount4ba18202015-07-27 12:39:28 -07001229public final TextView firstName;
1230public final TextView lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001231</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001232<p>
1233 IDs are not nearly as necessary as without data binding, but there are still
1234 some instances where access to Views are still necessary from code.
1235</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001236
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001237<h3 id="variables2">
1238 Variables
1239</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001240
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001241<p>
1242 Each variable will be given accessor methods.
1243</p>
1244
1245<pre>
George Mount4ba18202015-07-27 12:39:28 -07001246&lt;data&gt;
1247 &lt;import type="android.graphics.drawable.Drawable"/&gt;
1248 &lt;variable name="user" type="com.example.User"/&gt;
1249 &lt;variable name="image" type="Drawable"/&gt;
1250 &lt;variable name="note" type="String"/&gt;
1251&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001252</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001253<p>
1254 will generate setters and getters in the binding:
1255</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001256
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001257<pre>
George Mount4ba18202015-07-27 12:39:28 -07001258public abstract com.example.User getUser();
1259public abstract void setUser(com.example.User user);
1260public abstract Drawable getImage();
1261public abstract void setImage(Drawable image);
1262public abstract String getNote();
1263public abstract void setNote(String note);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001264</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001265<h3 id="viewstubs">
1266 ViewStubs
1267</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001268
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001269<p>
George Mount4ba18202015-07-27 12:39:28 -07001270 {@link android.view.ViewStub}s are a little different from normal Views. They start off invisible
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001271 and when they either are made visible or are explicitly told to inflate, they
1272 replace themselves in the layout by inflating another layout.
1273</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001274
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001275<p>
George Mount4ba18202015-07-27 12:39:28 -07001276 Because the <code>ViewStub</code> essentially disappears from the View hierarchy, the View
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001277 in the binding object must also disappear to allow collection. Because the
George Mount4ba18202015-07-27 12:39:28 -07001278 Views are final, a {@link android.databinding.ViewStubProxy} object takes the place of the
1279 <code>ViewStub</code>, giving the developer access to the ViewStub when it exists and also
1280 access to the inflated View hierarchy when the <code>ViewStub</code> has been inflated.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001281</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001282
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001283<p>
1284 When inflating another layout, a binding must be established for the new
George Mount4ba18202015-07-27 12:39:28 -07001285 layout. Therefore, the <code>ViewStubProxy</code> must listen to the <code>ViewStub</code>&apos;s
1286 {@link android.view.ViewStub.OnInflateListener} and establish the binding at that time. Since
1287 only one can exist, the <code>ViewStubProxy</code> allows the developer to set an
1288 <code>OnInflateListener</code> on it that it will call after establishing the binding.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001289</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001290
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001291<h3 id="advanced_binding">
1292 Advanced Binding
1293</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001294
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001295<h4 id="dynamic_variables">
1296 Dynamic Variables
1297</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001298
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001299<p>
1300 At times, the specific binding class won&apos;t be known. For example, a
George Mount4ba18202015-07-27 12:39:28 -07001301 {@link android.support.v7.widget.RecyclerView.Adapter} operating against arbitrary layouts
1302 won&apos;t know the specific binding class. It still must assign the binding value during the
1303 {@link android.support.v7.widget.RecyclerView.Adapter#onBindViewHolder}.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001304</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001305
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001306<p>
1307 In this example, all layouts that the RecyclerView binds to have an "item"
George Mount4ba18202015-07-27 12:39:28 -07001308 variable. The <code>BindingHolder</code> has a <code>getBinding</code> method returning the
1309 {@link android.databinding.ViewDataBinding} base.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001310</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001311
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001312<pre>
George Mount4ba18202015-07-27 12:39:28 -07001313public void onBindViewHolder(BindingHolder holder, int position) {
1314 final T item = mItems.get(position);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001315 holder.getBinding().setVariable(BR.item, item);
1316 holder.getBinding().executePendingBindings();
1317}
1318</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001319<h4 id="immediate_binding">
1320 Immediate Binding
1321</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001322
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001323<p>
1324 When a variable or observable changes, the binding will be scheduled to
1325 change before the next frame. There are times, however, when binding must be
1326 executed immediately. To force execution, use the
George Mount4ba18202015-07-27 12:39:28 -07001327 {@link android.databinding.ViewDataBinding#executePendingBindings()} method.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001328</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001329
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001330<h4>
1331 Background Thread
1332</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001333
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001334<p>
1335 You can change your data model in a background thread as long as it is not a
1336 collection. Data binding will localize each variable / field while evaluating
1337 to avoid any concurrency issues.
1338</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001339
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001340<h2 id="attribute_setters">
1341 Attribute Setters
1342</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001343
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001344<p>
1345 Whenever a bound value changes, the generated binding class must call a
1346 setter method on the View with the binding expression. The data binding
1347 framework has ways to customize which method to call to set the value.
1348</p>
1349
1350<h3 id="automatic_setters">
1351 Automatic Setters
1352</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001353For an attribute, data binding tries to find the method setAttribute. The
1354namespace for the attribute does not matter, only the attribute name itself.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001355<p>
1356 For example, an expression associated with TextView&apos;s attribute
1357 <strong><code>android:text</code></strong> will look for a setText(String).
1358 If the expression returns an int, data binding will search for a setText(int)
1359 method. Be careful to have the expression return the correct type, casting if
1360 necessary. Note that data binding will work even if no attribute exists with
1361 the given name. You can then easily "create" attributes for any setter by
1362 using data binding. For example, support DrawerLayout doesn&apos;t have any
1363 attributes, but plenty of setters. You can use the automatic setters to use
1364 one of these.
1365</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001366
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001367<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001368&lt;android.support.v4.widget.<strong>DrawerLayout
1369 android:layout_width="wrap_content"
1370 android:layout_height="wrap_content"
1371 app:scrimColor="&commat;{&commat;color/scrim}"
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001372 app:drawerListener="&commat;{fragment.drawerListener}"/&gt;</strong>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001373</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001374<h3 id="renamed_setters">
1375 Renamed Setters
1376</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001377
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001378<p>
1379 Some attributes have setters that don&apos;t match by name. For these
1380 methods, an attribute may be associated with the setter through
George Mount4ba18202015-07-27 12:39:28 -07001381 {@link android.databinding.BindingMethods} annotation. This must be associated with
1382 a class and contains {@link android.databinding.BindingMethod} annotations, one for
1383 each renamed method. For example, the <strong><code>android:tint</code></strong> attribute
1384 is really associated with {@link android.widget.ImageView#setImageTintList}, not
1385 <code>setTint</code>.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001386</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001387
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001388<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001389&commat;BindingMethods({
George Mount4ba18202015-07-27 12:39:28 -07001390 &commat;BindingMethod(type = "android.widget.ImageView",
1391 attribute = "android:tint",
1392 method = "setImageTintList"),
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001393})
1394</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001395<p>
1396 It is unlikely that developers will need to rename setters; the android
1397 framework attributes have already been implemented.
1398</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001399
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001400<h3 id="custom_setters">
1401 Custom Setters
1402</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001403
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001404<p>
1405 Some attributes need custom binding logic. For example, there is no
1406 associated setter for the <strong><code>android:paddingLeft</code></strong>
1407 attribute. Instead, <code>setPadding(left, top, right, bottom)</code> exists.
George Mount4ba18202015-07-27 12:39:28 -07001408 A static binding adapter method with the {@link android.databinding.BindingAdapter}
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001409 annotation allows the developer to customize how a setter for an attribute is
1410 called.
1411</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001412
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001413<p>
1414 The android attributes have already had <code>BindingAdapter</code>s created.
1415 For example, here is the one for <code>paddingLeft</code>:
1416</p>
1417
1418<pre>
George Mount4ba18202015-07-27 12:39:28 -07001419&commat;BindingAdapter("android:paddingLeft")
1420public static void setPaddingLeft(View view, int padding) {
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001421 view.setPadding(padding,
1422 view.getPaddingTop(),
1423 view.getPaddingRight(),
1424 view.getPaddingBottom());
1425}
1426</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001427<p>
1428 Binding adapters are useful for other types of customization. For example, a
1429 custom loader can be called off-thread to load an image.
1430</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001431
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001432<p>
1433 Developer-created binding adapters will override the data binding default
1434 adapters when there is a conflict.
1435</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001436
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001437<p>
1438 You can also have adapters that receive multiple parameters.
1439</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001440
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001441<pre>
George Mount4ba18202015-07-27 12:39:28 -07001442&commat;BindingAdapter({"bind:imageUrl", "bind:error"})
1443public static void loadImage(ImageView view, String url, Drawable error) {
1444 Picasso.with(view.getContext()).load(url).error(error).into(view);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001445}
1446</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001447<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001448&lt;ImageView app:imageUrl=“&commat;{venue.imageUrl}”
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001449app:error=“&commat;{&commat;drawable/venueError}”/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001450</pre>
1451
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001452<p>
1453 This adapter will be called if both <strong>imageUrl</strong> and
1454 <strong>error</strong> are used for an ImageView and <em>imageUrl</em> is a
1455 string and <em>error</em> is a drawable.
1456</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001457
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001458<ul>
1459 <li>Custom namespaces are ignored during matching.
1460 </li>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001461
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001462 <li>You can also write adapters for android namespace.
1463 </li>
1464</ul>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001465
George Mount4ba18202015-07-27 12:39:28 -07001466<p>
1467 Binding adapter methods may optionally take the old values in their handlers. A method
1468 taking old and new values should have all old values for the attributes come first, followed
1469 by the new values:
1470</p>
1471<pre>
1472&commat;BindingAdapter("android:paddingLeft")
1473public static void setPaddingLeft(View view, int oldPadding, int newPadding) {
1474 if (oldPadding != newPadding) {
1475 view.setPadding(newPadding,
1476 view.getPaddingTop(),
1477 view.getPaddingRight(),
1478 view.getPaddingBottom());
1479 }
1480}
1481</pre>
1482<p>
1483 Event handlers may only be used with interfaces or abstract classes with one abstract method.
1484 For example:
1485</p>
1486<pre>
1487&commat;BindingAdapter("android:onLayoutChange")
1488public static void setOnLayoutChangeListener(View view, View.OnLayoutChangeListener oldValue,
1489 View.OnLayoutChangeListener newValue) {
1490 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
1491 if (oldValue != null) {
1492 view.removeOnLayoutChangeListener(oldValue);
1493 }
1494 if (newValue != null) {
1495 view.addOnLayoutChangeListener(newValue);
1496 }
1497 }
1498}
1499</pre>
1500<p>
1501 When a listener has multiple methods, it must be split into multiple listeners. For example,
1502 {@link android.view.View.OnAttachStateChangeListener} has two methods:
1503 {@link android.view.View.OnAttachStateChangeListener#onViewAttachedToWindow onViewAttachedToWindow()} and
1504 {@link android.view.View.OnAttachStateChangeListener#onViewDetachedFromWindow onViewDetachedFromWindow()}.
1505 We must then create two interfaces to differentiate the attributes and handlers for them.
1506</p>
1507
1508<pre>
1509&commat;TargetApi(VERSION_CODES.HONEYCOMB_MR1)
1510public interface OnViewDetachedFromWindow {
1511 void onViewDetachedFromWindow(View v);
1512}
1513
1514&commat;TargetApi(VERSION_CODES.HONEYCOMB_MR1)
1515public interface OnViewAttachedToWindow {
1516 void onViewAttachedToWindow(View v);
1517}
1518</pre>
1519<p>
1520 Because changing one listener will also affect the other, we must have three different
1521 binding adapters, one for each attribute and one for both, should they both be set.
1522</p>
1523<pre>
1524&commat;BindingAdapter("android:onViewAttachedToWindow")
1525public static void setListener(View view, OnViewAttachedToWindow attached) {
1526 setListener(view, null, attached);
1527}
1528
1529&commat;BindingAdapter("android:onViewDetachedFromWindow")
1530public static void setListener(View view, OnViewDetachedFromWindow detached) {
1531 setListener(view, detached, null);
1532}
1533
1534&commat;BindingAdapter({"android:onViewDetachedFromWindow", "android:onViewAttachedToWindow"})
1535public static void setListener(View view, final OnViewDetachedFromWindow detach,
1536 final OnViewAttachedToWindow attach) {
1537 if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) {
1538 final OnAttachStateChangeListener newListener;
1539 if (detach == null && attach == null) {
1540 newListener = null;
1541 } else {
1542 newListener = new OnAttachStateChangeListener() {
1543 &commat;Override
1544 public void onViewAttachedToWindow(View v) {
1545 if (attach != null) {
1546 attach.onViewAttachedToWindow(v);
1547 }
1548 }
1549
1550 &commat;Override
1551 public void onViewDetachedFromWindow(View v) {
1552 if (detach != null) {
1553 detach.onViewDetachedFromWindow(v);
1554 }
1555 }
1556 };
1557 }
1558 final OnAttachStateChangeListener oldListener = ListenerUtil.trackListener(view,
1559 newListener, R.id.onAttachStateChangeListener);
1560 if (oldListener != null) {
1561 view.removeOnAttachStateChangeListener(oldListener);
1562 }
1563 if (newListener != null) {
1564 view.addOnAttachStateChangeListener(newListener);
1565 }
1566 }
1567}
1568</pre>
1569<p>
1570 The above example is slightly more complicated than normal because View uses add and remove
1571 for the listener instead of a set method for {@link android.view.View.OnAttachStateChangeListener}.
1572 The <code>android.databinding.adapters.ListenerUtil</code> class helps keep track of the previous
1573 listeners so that they may be removed in the Binding Adaper.
1574</p>
1575<p>
1576 By annotating the interfaces <code>OnViewDetachedFromWindow</code> and
1577 <code>OnViewAttachedToWindow</code> with
1578 <code>&commat;TargetApi(VERSION_CODES.HONEYCOMB_MR1)</code>, the data binding code
1579 generator knows that the listener should only be generated when running on Honeycomb MR1
1580 and new devices, the same version supported by
1581 {@link android.view.View#addOnAttachStateChangeListener}.
1582</p>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001583<h2 id="converters">
1584 Converters
1585</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001586
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001587<h3 id="object_conversions">
1588 Object Conversions
1589</h3>
1590
1591<p>
1592 When an Object is returned from a binding expression, a setter will be chosen
1593 from the automatic, renamed, and custom setters. The Object will be cast to a
1594 parameter type of the chosen setter.
1595</p>
1596
1597<p>
1598 This is a convenience for those using ObservableMaps to hold data. for
1599 example:
1600</p>
1601
1602<pre>
George Mount4ba18202015-07-27 12:39:28 -07001603&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001604 android:text=&apos;&commat;{userMap["lastName"]}&apos;
1605 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001606 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001607</pre>
1608
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001609<p>
1610The <code>userMap</code> returns an Object and that Object will be automatically cast to
1611 parameter type found in the setter <code>setText(CharSequence)</code>. When there
1612 may be confusion about the parameter type, the developer will need
1613 to cast in the expression.
1614</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001615
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001616<h3 id="custom_conversions">Custom Conversions</h3>
1617
1618<p>
1619 Sometimes conversions should be automatic between specific types. For
1620 example, when setting the background:
1621</p>
1622
1623<pre>
George Mount4ba18202015-07-27 12:39:28 -07001624&lt;View
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001625 android:background="&commat;{isError ? &commat;color/red : &commat;color/white}"
1626 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001627 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001628</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001629<p>
1630 Here, the background takes a <code>Drawable</code>, but the color is an
1631 integer. Whenever a <code>Drawable</code> is expected and an integer is
1632 returned, the <code>int</code> should be converted to a
1633 <code>ColorDrawable</code>. This conversion is done using a static method
1634 with a BindingConversion annotation:
1635</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001636
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001637<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001638&commat;BindingConversion
George Mount4ba18202015-07-27 12:39:28 -07001639public static ColorDrawable convertColorToDrawable(int color) {
1640 return new ColorDrawable(color);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001641}
1642</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001643<p>
1644 Note that conversions only happen at the setter level, so it is <strong>not
1645 allowed</strong> to mix types like this:
1646</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001647
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001648<pre>
George Mount4ba18202015-07-27 12:39:28 -07001649&lt;View
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001650 android:background="&commat;{isError ? &commat;drawable/error : &commat;color/white}"
1651 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001652 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001653</pre>
Daniel Yudaa41bb2015-12-08 10:58:07 -08001654
1655<h3 id="studio_support">Android Studio Support for Data Binding</h3>
1656
1657<p>
Cheryl Potter8dd7eea2016-04-04 17:10:06 -07001658Android Studio supports many of the code editing features for data binding code.
1659For example, it supports the following features for data binding expressions:</p>
1660<ul>
1661<li>Syntax highlighting</li>
1662<li>Flagging of expression language syntax errors</li>
1663<li>XML code completion</li>
1664<li>References, including <a class="external-link"
1665href="https://www.jetbrains.com/help/idea/2016.1/navigation-in-source-code.html?origin=old_help">
1666navigation</a> (such as navigate to a declaration) and
1667<a class="external-link"
1668href="https://www.jetbrains.com/help/idea/2016.1/viewing-inline-documentation.html?origin=old_help">
1669quick documentation</a></li>
1670</ul>
1671
1672<p class="note"><strong>Note:</strong> Arrays and a
1673<a href="https://docs.oracle.com/javase/tutorial/java/generics/types.html"
1674class="external-link">generic type</a>, such as the {@link
1675android.databinding.Observable} class, might display
1676errors when there are no errors.</p>
1677
Daniel Yudaa41bb2015-12-08 10:58:07 -08001678<p>
Cheryl Potter8dd7eea2016-04-04 17:10:06 -07001679The Preview pane displays default values for data binding expressions if
1680provided. In the following
1681example excerpt of an element from a layout XML file, the Preview pane displays
1682the {@code PLACEHOLDER} default text value in the <code>TextView</code>.
Daniel Yudaa41bb2015-12-08 10:58:07 -08001683</p>
1684
1685<pre>
1686&lt;TextView android:layout_width="wrap_content"
1687 android:layout_height="wrap_content"
1688 android:text="&commat;{user.firstName, default=PLACEHOLDER}"/&gt;
1689</pre>
1690
1691<p>
Cheryl Potter8dd7eea2016-04-04 17:10:06 -07001692If you need to display a default value during the design phase of your project,
1693you can also use tools attributes instead of default expression values, as
1694described in
1695<a class="external-link"
1696href="http://tools.android.com/tips/layout-designtime-attributes">
Daniel Yudaa41bb2015-12-08 10:58:07 -08001697Designtime Layout Attributes</a>.
Cheryl Potter8dd7eea2016-04-04 17:10:06 -07001698</p>
1699