blob: 2de5bc209d55f8f91a58d42161437ffb09fe5378 [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>
134 </ol>
135 </div><!-- qv -->
136</div><!-- qv-wrapper -->
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700137
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700138<p>
139 This document explains how to use the Data Binding Library to write
140 declarative layouts and minimize the glue code necessary to bind your
141 application logic and layouts.
142</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700143
Dirk Dougherty08710f12015-05-28 22:01:36 -0700144<p>The Data Binding Library offers both flexibility and broad comnpatibility
145&mdash; it's a support library, so you can use it with all Android platform
146versions back to <strong>Android 2.1</strong> (API level 7+).</p>
147
George Mount4ba18202015-07-27 12:39:28 -0700148<p>To use data binding, Android Plugin for Gradle <strong>1.3.0-beta4</strong>
Dirk Doughertybcab1822015-06-02 14:05:31 -0700149or higher is required.</p>
Dirk Dougherty08710f12015-05-28 22:01:36 -0700150
151<h4>Beta release</h4>
152
153<div class="caution">
154 <p>Please note that the Data Binding library is a <strong>beta release</strong>.
155 While Data Binding is in beta, developers should be aware of the following
156 caveats:</p>
157 <ul>
158 <li>
159 This is a beta release of the feature intended to generate developer
160 feedback. It might contain bugs, and it might not work for your use case,
161 so use it at your own risk. That said, we do want your feedback! Please
162 let us know what is or isn’t working for you using the <a
163 href="https://code.google.com/p/android-developer-preview/">issue
Dirk Doughertybcab1822015-06-02 14:05:31 -0700164 tracker</a>.
Dirk Dougherty08710f12015-05-28 22:01:36 -0700165 </li>
166 <li>
167 The Data Binding library beta release is subject to significant changes,
168 including those which are not source code compatible with your app. That is,
169 significant rework may be required to take updates to the library in the future.
170 </li>
171 <li>
172 Developers should feel free to publish apps built with the Data Binding
173 library beta release, with the caveats that the standard Android SDK and
174 Google Play terms of service apply, and it’s always a great idea to test your
175 app thoroughly when adopting new libraries or tools.
176 </li>
177 <li>
178 We’re just getting started with Android Studio support at this time.
179 Further Android Studio support will come in the future.
180 </li>
181 <li>
Dirk Doughertybcab1822015-06-02 14:05:31 -0700182 By using the Data Binding library beta release, you acknowledge these
Dirk Dougherty08710f12015-05-28 22:01:36 -0700183 caveats.</li>
184 </ul>
185</div>
186
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700187<h2 id="build_environment">
188 Build Environment
189</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700190
Dirk Dougherty08710f12015-05-28 22:01:36 -0700191<p>To get started with Data Binding, download the library from the Support
192repository in the Android SDK manager. </p>
193
George Mount4ba18202015-07-27 12:39:28 -0700194<p>The Data Binding plugin requires Android Plugin for Gradle <strong>1.3.0-beta4
195or higher</strong>, so update your build dependencies (in the top-level
196<code>build.gradle</code> file) as needed.</p>
Dirk Dougherty08710f12015-05-28 22:01:36 -0700197
Dirk Doughertybcab1822015-06-02 14:05:31 -0700198<p>Also, make sure you are using a compatible version of Android Studio.
199<strong>Android Studio 1.3</strong> adds the code-completion and layout-preview
200support for data binding.</p>
Dirk Dougherty08710f12015-05-28 22:01:36 -0700201
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700202<p>
203 <strong>Setting Up Work Environment:</strong>
204</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700205
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700206<p>
207 To set up your application to use data binding, add data binding to the class
George Mount4ba18202015-07-27 12:39:28 -0700208 path of your top-level <code>build.gradle</code> file, right below "android".
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700209</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700210
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700211<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700212 dependencies {
George Mount4ba18202015-07-27 12:39:28 -0700213 classpath <strong>"com.android.tools.build:gradle:1.3.0-beta4"</strong>
214 classpath <strong>"com.android.databinding:dataBinder:1.0-rc1"</strong>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700215 }
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700216</pre>
217<p>
George Mount4ba18202015-07-27 12:39:28 -0700218 Then make sure jcenter is in the repositories list for your projects in the top-level
219 <code>build.gradle</code> file.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700220</p>
221
222<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700223allprojects {
224 repositories {
225 jcenter()
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700226 }
227}
228</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700229<p>
230 In each module you want to use data binding, apply the plugin right after
231 android plugin
232</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700233
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700234<pre>
George Mount4ba18202015-07-27 12:39:28 -0700235apply plugin: &apos;com.android.application&apos;
236apply plugin: &apos;com.android.databinding&apos;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700237</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700238<p>
239 The data binding plugin is going to add necessary <strong>provided</strong>
240 and <strong>compile configuration</strong> dependencies to your project.
241</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700242
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700243<h2 id="data_binding_layout_files">
244 Data Binding Layout Files
245</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700246
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700247<h3 id="writing_expressions">
248 Writing your first data binding expressions
249</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700250
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700251<p>
252 Data-binding layout files are slightly different and start with a root tag of
253 <strong>layout</strong> followed by a <strong>data</strong> element and a
254 <strong>view</strong> root element. This view element is what your root would
255 be in a non-binding layout file. A sample file looks like this:
256</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700257
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700258<pre>
George Mount4ba18202015-07-27 12:39:28 -0700259&lt;?xml version="1.0" encoding="utf-8"?&gt;
260&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"&gt;
261 &lt;data&gt;
262 &lt;variable name="user" type="com.example.User"/&gt;
263 &lt;/data&gt;
264 &lt;LinearLayout
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700265 android:orientation="vertical"
266 android:layout_width="match_parent"
George Mount4ba18202015-07-27 12:39:28 -0700267 android:layout_height="match_parent"&gt;
268 &lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700269 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700270 android:text="&commat;{user.firstName}"/&gt;
271 &lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700272 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700273 android:text="&commat;{user.lastName}"/&gt;
274 &lt;/LinearLayout&gt;
275&lt;/layout&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700276</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700277<p>
278 The user <strong>variable</strong> within <strong>data</strong> describes a
279 property that may be used within this layout.
280</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700281
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700282<pre>
283&lt;<strong>variable name="user" type="com.example.User"</strong>/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700284</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700285<p>
286 Expressions within the layout are written in the attribute properties using
287 the “<code>&commat;{}</code>” syntax. Here, the TextView’s text is set to the
288 firstName property of user:
289</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700290
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700291<pre>
George Mount4ba18202015-07-27 12:39:28 -0700292&lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700293 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700294 android:text="&commat;{user.firstName}"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700295</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700296<h3 id="data_object">
297 Data Object
298</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700299
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700300<p>
301 Let’s assume for now that you have a plain-old Java object (POJO) for User:
302</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700303
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700304<pre>
George Mount4ba18202015-07-27 12:39:28 -0700305public class User {
306 public final String firstName;
307 public final String lastName;
308 public User(String firstName, String lastName) {
309 this.firstName = firstName;
310 this.lastName = lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700311 }
312}
313</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700314<p>
315 This type of object has data that never changes. It is common in applications
316 to have data that is read once and never changes thereafter. It is also
317 possible to use a JavaBeans objects:
318</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700319
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700320<pre>
George Mount4ba18202015-07-27 12:39:28 -0700321public class User {
322 private final String firstName;
323 private final String lastName;
324 public User(String firstName, String lastName) {
325 this.firstName = firstName;
326 this.lastName = lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700327 }
George Mount4ba18202015-07-27 12:39:28 -0700328 public String getFirstName() {
329 return this.firstName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700330 }
George Mount4ba18202015-07-27 12:39:28 -0700331 public String getLastName() {
332 return this.lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700333 }
334}
335</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700336<p>
337 From the perspective of data binding, these two classes are equivalent. The
338 expression <strong><code>&commat;{user.firstName}</code></strong> used for
339 the TextView’s <strong><code>android:text</code></strong> attribute will
340 access the <strong><code>firstName</code></strong> field in the former class
George Mount4ba18202015-07-27 12:39:28 -0700341 and the <code>getFirstName()</code> method in the latter class. Alternatively, it
342 will also be resolved to <code>firstName()</code> if that method exists.
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700343</p>
344
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700345<h3 id="binding_data">
346 Binding Data
347</h3>
348
349<p>
350 By default, a Binding class will be generated based on the name of the layout
351 file, converting it to Pascal case and suffixing “Binding” to it. The above
George Mount4ba18202015-07-27 12:39:28 -0700352 layout file was <code>main_activity.xml</code> so the generate class was
353 <code>MainActivityBinding</code>. This class holds all the bindings from the
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700354 layout properties (e.g. the <code>user</code> variable) to the layout’s Views
355 and knows how to assign values for the binding expressions.The easiest means
356 for creating the bindings is to do it while inflating:
357</p>
358
359<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700360&commat;Override
George Mount4ba18202015-07-27 12:39:28 -0700361protected void onCreate(Bundle savedInstanceState) {
362 super.onCreate(savedInstanceState);
363 MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
364 User user = new User("Test", "User");
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700365 binding.setUser(user);
366}
367</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700368<p>
369 You’re done! Run the application and you’ll see Test User in the UI.
370 Alternatively, you can get the view via:
371</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700372
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700373<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700374MainActivityBinding binding = MainActivityBinding.<em>inflate</em>(getLayoutInflater());
375</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700376<p>
377 If you are using data binding items inside a ListView or RecyclerView
378 adapter, you may prefer to use:
379</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700380
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700381<pre>
George Mount4ba18202015-07-27 12:39:28 -0700382ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700383//or
384ListItemBinding binding = DataBindingUtil.<em>inflate</em>(layoutInflater, R.layout.<em><strong>list_item</strong></em>, viewGroup, <strong>false</strong>);
385</pre>
George Mount4ba18202015-07-27 12:39:28 -0700386
387<h3 id="binding_events">
388 Binding Events
389</h3>
390<p>
391 Events may be bound to handler methods directly, similar to the way
392 <strong><code>android:onClick</code></strong> can be assigned to a method in the Activity.
393 Event attribute names are governed by the name of the listener method with a few exceptions.
394 For example, {@link android.view.View.OnLongClickListener} has a method {@link android.view.View.OnLongClickListener#onLongClick onLongClick()},
395 so the attribute for this event is <code>android:onLongClick</code>.
396</p>
397<p>
398 To assign an event to its handler, use a normal binding expression, with the value
399 being the method name to call. For example, if your data object has two methods:
400</p>
401<pre>public class MyHandlers {
402 public void onClickFriend(View view) { ... }
403 public void onClickEnemy(View view) { ... }
404}
405</pre>
406<p>
407 The binding expression can assign the click listener for a View:
408</p>
409<pre>
410&lt;?xml version="1.0" encoding="utf-8"?&gt;
411&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"&gt;
412 &lt;data&gt;
413 &lt;variable name="handlers" type="com.example.Handlers"/&gt;
414 &lt;variable name="user" type="com.example.User"/&gt;
415 &lt;/data&gt;
416 &lt;LinearLayout
417 android:orientation="vertical"
418 android:layout_width="match_parent"
419 android:layout_height="match_parent"&gt;
420 &lt;TextView android:layout_width="wrap_content"
421 android:layout_height="wrap_content"
422 android:text="&commat;{user.firstName}"
423 android:onClick="&commat;{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/&gt;
424 &lt;TextView android:layout_width="wrap_content"
425 android:layout_height="wrap_content"
426 android:text="&commat;{user.lastName}"
427 android:onClick="&commat;{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/&gt;
428 &lt;/LinearLayout&gt;
429&lt;/layout&gt;
430</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700431<h2 id="layout_details">
432 Layout Details
433</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700434
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700435<h3 id="imports">
436 Imports
437</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700438
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700439<p>
440 Zero or more <strong><code>import</code></strong> elements may be used inside
441 the <strong><code>data</code></strong> element. These allow easy reference to
442 classes inside your layout file, just like in Java.
443</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700444
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700445<pre>
George Mount4ba18202015-07-27 12:39:28 -0700446&lt;data&gt;
447 &lt;import type="android.view.View"/&gt;
448&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700449</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700450<p>
451 Now, View may be used within your binding expression:
452</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700453
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700454<pre>
George Mount4ba18202015-07-27 12:39:28 -0700455&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700456 android:text="&commat;{user.lastName}"
457 android:layout_width="wrap_content"
458 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700459 android:visibility="&commat;{user.isAdult ? View.VISIBLE : View.GONE}"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700460</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700461<p>
462 When there are class name conflicts, one of the classes may be renamed to an
463 “alias:”
464</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700465
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700466<pre>
George Mount4ba18202015-07-27 12:39:28 -0700467&lt;import type="android.view.View"/&gt;
468&lt;import type="com.example.real.estate.View"
469 alias="Vista"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700470</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700471<p>
472 Now, <strong><code>Vista</code></strong> may be used to reference the
473 <code>com.example.real.estate.View</code> and
474 <strong><code>View</code></strong> may be used to reference
475 <code>android.view.View</code> within the layout file. Imported types may be
476 used as type references in variables and 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.User"/&gt;
482 &lt;import type="java.util.List"/&gt;
483 &lt;variable name="user" type="User"/&gt;
484 &lt;variable name="userList" type="List&amp;lt;User&gt;"/&gt;
485&lt;/data&gt;
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700486</pre>
Dirk Dougherty08710f12015-05-28 22:01:36 -0700487<p class="caution">
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700488 <strong>Note</strong>: Android Studio does not yet handle imports so the
489 autocomplete for imported variables may not work in your IDE. Your
490 application will still compile fine and you can work around the IDE issue by
491 using fully qualified names in your variable definitions.
492</p>
493
494<pre>
George Mount4ba18202015-07-27 12:39:28 -0700495&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700496 android:text="&commat;{((User)(user.connection)).lastName}"
497 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700498 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700499</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700500<p>
501 Imported types may also be used when referencing static fields and methods in
502 expressions:
503</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700504
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700505<pre>
George Mount4ba18202015-07-27 12:39:28 -0700506&lt;data&gt;
507 &lt;import type="com.example.MyStringUtils"/&gt;
508 &lt;variable name="user" type="com.example.User"/&gt;
509&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700510
George Mount4ba18202015-07-27 12:39:28 -0700511&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700512 android:text="&commat;{MyStringUtils.capitalize(user.lastName)}"
513 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -0700514 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700515</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700516<p>
517 Just as in Java, <code>java.lang.*</code> is imported automatically.
518</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700519
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700520<h3 id="variables">
521 Variables
522</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700523
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700524<p>
525 Any number of <strong><code>variable</code></strong> elements may be used
526 inside the <strong><code>data</code></strong> element. Each
527 <strong><code>variable</code></strong> element describes a property that may
528 be set on the layout to be used in binding expressions within the layout
529 file.
530</p>
531
532<pre>
George Mount4ba18202015-07-27 12:39:28 -0700533&lt;data&gt;
534 &lt;import type="android.graphics.drawable.Drawable"/&gt;
535 &lt;variable name="user" type="com.example.User"/&gt;
536 &lt;variable name="image" type="Drawable"/&gt;
537 &lt;variable name="note" type="String"/&gt;
538&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700539</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700540<p>
541 The variable types are inspected at compile time, so if a variable implements
George Mount4ba18202015-07-27 12:39:28 -0700542 {@link android.databinding.Observable} or is an <a href=
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700543 "#observable_collections">observable collection</a>, that should be reflected
544 in the type. If the variable is a base class or interface that does not
545 implement the Observable* interface, the variables will <strong>not
546 be</strong> observed!
547</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700548
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700549<p>
550 When there are different layout files for various configurations (e.g.
551 landscape or portrait), the variables will be combined. There must not be
552 conflicting variable definitions between these layout files.
553</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700554
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700555<p>
556 The generated binding class will have a setter and getter for each of the
557 described variables. The variables will take the default Java values until
558 the setter is called &mdash; <code>null</code> for reference types,
559 <code>0</code> for <code>int</code>, <code>false</code> for
560 <code>boolean</code>, etc.
561</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700562
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700563<h3 id="custom_binding_class_names">
564 Custom Binding Class Names
565</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700566
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700567<p>
568 By default, a Binding class is generated based on the name of the layout
569 file, starting it with upper-case, removing underscores ( _ ) and
570 capitalizing the following letter and then suffixing “Binding”. This class
571 will be placed in a databinding package under the module package. For
572 example, the layout file <code>contact_item.xml</code> will generate
573 <code>ContactItemBinding</code>. If the module package is
574 <code>com.example.my.app</code>, then it will be placed in
575 <code>com.example.my.app.databinding</code>.
576</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700577
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700578<p>
579 Binding classes may be renamed or placed in different packages by adjusting
580 the <strong><code>class</code></strong> attribute of the
581 <strong><code>data</code></strong> element. For example:
582</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700583
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700584<pre>
George Mount4ba18202015-07-27 12:39:28 -0700585&lt;data class="ContactItem"&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700586 ...
George Mount4ba18202015-07-27 12:39:28 -0700587&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700588</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700589<p>
590 This generates the binding class as <code>ContactItem</code> in the
591 databinding package in the module package. If the class should be generated
592 in a different package within the module package, it may be prefixed with
593 “.”:
594</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700595
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700596<pre>
George Mount4ba18202015-07-27 12:39:28 -0700597&lt;data class=".ContactItem"&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700598 ...
George Mount4ba18202015-07-27 12:39:28 -0700599&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700600</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700601<p>
602 In this case, <code>ContactItem</code> is generated in the module package
603 directly. Any package may be used if the full package is provided:
604</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700605
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700606<pre>
George Mount4ba18202015-07-27 12:39:28 -0700607&lt;data class="com.example.ContactItem"&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700608 ...
George Mount4ba18202015-07-27 12:39:28 -0700609&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700610</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700611<h3 id="includes">
612 Includes
613</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700614
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700615<p>
616 Variables may be passed into an included layout&apos;s binding from the
617 containing layout by using the application namespace and the variable name in
618 an attribute:
619</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700620
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700621<pre>
George Mount4ba18202015-07-27 12:39:28 -0700622&lt;?xml version="1.0" encoding="utf-8"?&gt;
623&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"
624 xmlns:bind="http://schemas.android.com/apk/res-auto"&gt;
625 &lt;data&gt;
626 &lt;variable name="user" type="com.example.User"/&gt;
627 &lt;/data&gt;
628 &lt;LinearLayout
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700629 android:orientation="vertical"
630 android:layout_width="match_parent"
George Mount4ba18202015-07-27 12:39:28 -0700631 android:layout_height="match_parent"&gt;
632 &lt;include layout="&commat;layout/name"
633 bind:user="&commat;{user}"/&gt;
634 &lt;include layout="&commat;layout/contact"
635 bind:user="&commat;{user}"/&gt;
636 &lt;/LinearLayout&gt;
637&lt;/layout&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700638</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700639<p>
640 Here, there must be a <code>user</code> variable in both the
641 <code>name.xml</code> and <code>contact.xml</code> layout files.
642</p>
George Mount4ba18202015-07-27 12:39:28 -0700643<p>
644 Data binding does not support include as a direct child of a merge element. For example,
645 <strong>the following layout is not supported:</strong>
646</p>
647<pre>
648&lt;?xml version="1.0" encoding="utf-8"?&gt;
649&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"
650 xmlns:bind="http://schemas.android.com/apk/res-auto"&gt;
651 &lt;data&gt;
652 &lt;variable name="user" type="com.example.User"/&gt;
653 &lt;/data&gt;
654 &lt;merge&gt;
655 &lt;include layout="&commat;layout/name"
656 bind:user="&commat;{user}"/&gt;
657 &lt;include layout="&commat;layout/contact"
658 bind:user="&commat;{user}"/&gt;
659 &lt;/merge&gt;
660&lt;/layout&gt;
661</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700662<h3 id="expression_language">
663 Expression Language
664</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700665
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700666<h4 id="common_features">
667 Common Features
668</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700669
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700670<p>
671 The expression language looks a lot like a Java expression. These are the
672 same:
673</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700674
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700675<ul>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700676 <li>Mathematical <strong><code>+ - / * %</code></strong>
677 </li>
678
679 <li>String concatenation <strong><code>+</code></strong>
680 </li>
681
682 <li>
George Mount4ba18202015-07-27 12:39:28 -0700683 Logical <strong><code>&& ||</code></strong>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700684 </li>
685
George Mount4ba18202015-07-27 12:39:28 -0700686 <li>Binary <strong><code>& | ^</code></strong>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700687 </li>
688
689 <li>Unary <strong><code>+ - ! ~</code></strong>
690 </li>
691
692 <li>Shift <strong><code>&gt;&gt; &gt;&gt;&gt; &lt;&lt;</code></strong>
693 </li>
694
695 <li>Comparison <strong><code>== &gt; &lt; &gt;= &lt;=</code></strong>
696 </li>
697
698 <li>
699 <strong><code>instanceof</code></strong>
700 </li>
701
702 <li>Grouping <strong><code>()</code></strong>
703 </li>
704
705 <li>Literals - character, String, numeric, <strong><code>null</code></strong>
706 </li>
707
708 <li>Cast
709 </li>
710
711 <li>Method calls
712 </li>
713
714 <li>Field access
715 </li>
716
717 <li>Array access <strong><code>[]</code></strong>
718 </li>
719
720 <li>Ternary operator <strong><code>?:</code></strong>
721 </li>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700722</ul>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700723
724<p>
725 Examples:
726</p>
727
728<pre>
George Mount4ba18202015-07-27 12:39:28 -0700729android:text="&commat;{String.valueOf(index + 1)}"
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700730android:visibility="&commat;{age &amp;lt; 13 ? View.GONE : View.VISIBLE}"
George Mount4ba18202015-07-27 12:39:28 -0700731android:transitionName=&apos;&commat;{"image_" + id}&apos;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700732</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700733<h4 id="missing_operations">
734 Missing Operations
735</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700736
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700737<p>
738 A few operations are missing from the expression syntax that you can use in
739 Java.
740</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700741
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700742<ul>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700743 <li>
744 <strong><code>this</code></strong>
745 </li>
746
747 <li>
748 <strong><code>super</code></strong>
749 </li>
750
751 <li>
752 <strong><code>new</code></strong>
753 </li>
754
755 <li>Explicit generic invocation
756 </li>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700757</ul>
758
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700759<h4 id="null_coalescing_operator">
760 Null Coalescing Operator
761</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700762
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700763<p>
764 The null coalescing operator (<strong><code>??</code></strong>) chooses the
765 left operand if it is not null or the right if it is null.
766</p>
767
768<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700769<strong>android:text="&commat;{user.displayName ?? user.lastName}"</strong>
770</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700771<p>
772 This is functionally equivalent to:
773</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700774
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700775<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700776<strong>android:text="&commat;{user.displayName != null ? user.displayName : user.lastName}"</strong>
777</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700778<h4 id="property_reference">
779 Property Reference
780</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700781
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700782<p>
783 The first was already discussed in the <a href=
784 "#writing_your_first_data_binding_expressions">Writing your first data
785 binding expressions</a> above: short form JavaBean references. When an
786 expression references a property on a class, it uses the same format for
787 fields, getters, and ObservableFields.
788</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700789
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700790<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700791<strong>android:text="&commat;{user.lastName}"</strong>
792</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700793<h4>
794 Avoiding NullPointerException
795</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700796
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700797<p>
798 Generated data binding code automatically checks for nulls and avoid null
799 pointer exceptions. For example, in the expression
800 <code>&commat;{user.name}</code>, if <code>user</code> is null,
801 <code>user.name</code> will be assigned its default value (null). If you were
802 referencing <code>user.age</code>, where age is an <code>int</code>, then it
803 would default to 0.
804</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700805
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700806<h4 id="collections">
807 Collections
808</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700809
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700810<p>
811 Common collections: arrays, lists, sparse lists, and maps, may be accessed
812 using the <code>[]</code> operator for convenience.
813</p>
814
815<pre>
George Mount4ba18202015-07-27 12:39:28 -0700816&lt;data&gt;
817 &lt;import type="android.util.SparseArray"/&gt;
818 &lt;import type="java.util.Map"/&gt;
819 &lt;import type="java.util.List"/&gt;
820 &lt;variable name="list" type="List&amp;lt;String&gt;"/&gt;
821 &lt;variable name="sparse" type="SparseArray&amp;lt;String&gt;"/&gt;
822 &lt;variable name="map" type="Map&amp;lt;String, String&gt;"/&gt;
823 &lt;variable name="index" type="int"/&gt;
824 &lt;variable name="key" type="String"/&gt;
825&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700826
George Mount4ba18202015-07-27 12:39:28 -0700827android:text="&commat;{list[index]}"
828
829android:text="&commat;{sparse[index]}"
830
831android:text="&commat;{map[key]}"
832
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700833</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700834<h4 id="string_literals">
835 String Literals
836</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700837
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700838<p>
839 When using single quotes around the attribute value, it is easy to use double
840 quotes in the expression:
841</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700842
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700843<pre>
George Mount4ba18202015-07-27 12:39:28 -0700844android:text=&apos;&commat;{map["firstName"]}&apos;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700845</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700846<p>
847 It is also possible to use double quotes to surround the attribute value.
848 When doing so, String literals should either use the &amp;quot; or back quote
849 (`).
850</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700851
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700852<pre>
George Mount4ba18202015-07-27 12:39:28 -0700853android:text="&commat;{map[`firstName`}"
854android:text="&commat;{map[&amp;quot;firstName&amp;quot;]}"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700855</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700856<h4 id="resources">
857 Resources
858</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700859
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700860<p>
861 It is possible to access resources as part of expressions using the normal
862 syntax:
863</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700864
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700865<pre>
George Mount4ba18202015-07-27 12:39:28 -0700866android:padding="&commat;{large? &commat;dimen/largePadding : &commat;dimen/smallPadding}"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700867</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700868<p>
869 Format strings and plurals may be evaluated by providing parameters:
870</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700871
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700872<pre>
George Mount4ba18202015-07-27 12:39:28 -0700873android:text="&commat;{&commat;string/nameFormat(firstName, lastName)}"
874android:text="&commat;{&commat;plurals/banana(bananaCount)}"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700875</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700876<p>
877 When a plural takes multiple parameters, all parameters should be passed:
878</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700879
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700880<pre>
881
882 Have an orange
883 Have %d oranges
884
George Mount4ba18202015-07-27 12:39:28 -0700885android:text="&commat;{&commat;plurals/orange(orangeCount, orangeCount)}"
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700886</pre>
887<p>
888 Some resources require explicit type evaluation.
889</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700890
891<table>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700892 <tr>
893 <th>
894 Type
895 </th>
896 <th>
897 Normal Reference
898 </th>
899 <th>
900 Expression Reference
901 </th>
902 </tr>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700903
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700904 <tr>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700905 <td>
George Mount4ba18202015-07-27 12:39:28 -0700906 String[]
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700907 </td>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700908 <td>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700909 &commat;array
910 </td>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700911 <td>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700912 &commat;stringArray
913 </td>
914 </tr>
915
916 <tr>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700917 <td>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700918 int[]
919 </td>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700920 <td>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700921 &commat;array
922 </td>
923 <td>
924 &commat;intArray
925 </td>
926 </tr>
927
928 <tr>
929 <td>
930 TypedArray
931 </td>
932 <td>
933 &commat;array
934 </td>
935 <td>
936 &commat;typedArray
937 </td>
938 </tr>
939
940 <tr>
941 <td>
942 Animator
943 </td>
944 <td>
945 &commat;animator
946 </td>
947 <td>
948 &commat;animator
949 </td>
950 </tr>
951
952 <tr>
953 <td>
954 StateListAnimator
955 </td>
956 <td>
957 &commat;animator
958 </td>
959 <td>
960 &commat;stateListAnimator
961 </td>
962 </tr>
963
964 <tr>
965 <td>
966 color <code>int</code>
967 </td>
968 <td>
George Mount4ba18202015-07-27 12:39:28 -0700969 &commat;color
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700970 </td>
971 <td>
972 &commat;color
973 </td>
974 </tr>
975
976 <tr>
977 <td>
978 ColorStateList
979 </td>
980 <td>
981 &commat;color
982 </td>
983 <td>
984 &commat;colorStateList
985 </td>
986 </tr>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700987</table>
988
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700989<h2 id="data_objects">
990 Data Objects
991</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -0700992
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -0700993<p>
994 Any plain old Java object (POJO) may be used for data binding, but modifying
995 a POJO will not cause the UI to update. The real power of data binding can be
996 used by giving your data objects the ability to notify when data changes.
997 There are three different data change notification mechanisms,
George Mount4ba18202015-07-27 12:39:28 -0700998 <a href="#observable_objects">Observable objects</a>,
999 <a href="#observablefields">observable fields</a>, and
1000 <a href="#observable_collections">observable collection</a>s.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001001</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001002
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001003<p>
1004 When one of these observable data object is bound to the UI and a property of
1005 the data object changes, the UI will be updated automatically.
1006</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001007
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001008<h3 id="observable_objects">
1009 Observable Objects
1010</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001011
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001012<p>
George Mount4ba18202015-07-27 12:39:28 -07001013 A class implementing the {@link android.databinding.Observable} interface
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001014 will allow the binding to attach a single listener to a bound object to
1015 listen for changes of all properties on that object.
1016</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001017
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001018<p>
George Mount4ba18202015-07-27 12:39:28 -07001019 The {@link android.databinding.Observable} interface has a mechanism to add and remove
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001020 listeners, but notifying is up to the developer. To make development easier,
George Mount4ba18202015-07-27 12:39:28 -07001021 a base class, {@link android.databinding.BaseObservable}, was created to implement the
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001022 listener registration mechanism. The data class implementer is still
1023 responsible for notifying when the properties change. This is done by
George Mount4ba18202015-07-27 12:39:28 -07001024 assigning a {@link android.databinding.Bindable} annotation to the getter and notifying in
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001025 the setter.
1026</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001027
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001028<pre>
George Mount4ba18202015-07-27 12:39:28 -07001029private static class User extends BaseObservable {
1030 private String firstName;
1031 private String lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001032 &commat;Bindable
George Mount4ba18202015-07-27 12:39:28 -07001033 public String getFirstName() {
1034 return this.firstName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001035 }
1036 &commat;Bindable
George Mount4ba18202015-07-27 12:39:28 -07001037 public String getLastName() {
1038 return this.lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001039 }
George Mount4ba18202015-07-27 12:39:28 -07001040 public void setFirstName(String firstName) {
1041 this.firstName = firstName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001042 notifyPropertyChanged(BR.firstName);
1043 }
George Mount4ba18202015-07-27 12:39:28 -07001044 public void setLastName(String lastName) {
1045 this.lastName = lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001046 notifyPropertyChanged(BR.lastName);
1047 }
1048}
1049</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001050<p>
George Mount4ba18202015-07-27 12:39:28 -07001051 The {@link android.databinding.Bindable} annotation generates an entry in the BR class file
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001052 during compilation. The BR class file will be generated in the module
George Mount4ba18202015-07-27 12:39:28 -07001053 package. If the base class for data classes cannot be changed, the
1054 {@link android.databinding.Observable} interface may be implemented using the convenient
1055 {@link android.databinding.PropertyChangeRegistry} to store and notify listeners
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001056 efficiently.
1057</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001058
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001059<h3 id="observablefields">
1060 ObservableFields
1061</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001062
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001063<p>
George Mount4ba18202015-07-27 12:39:28 -07001064 A little work is involved in creating {@link android.databinding.Observable} classes, so
1065 developers who want to save time or have few properties may use
1066 {@link android.databinding.ObservableField} and its siblings
1067 {@link android.databinding.ObservableBoolean},
1068 {@link android.databinding.ObservableByte},
1069 {@link android.databinding.ObservableChar},
1070 {@link android.databinding.ObservableShort},
1071 {@link android.databinding.ObservableInt},
1072 {@link android.databinding.ObservableLong},
1073 {@link android.databinding.ObservableFloat},
1074 {@link android.databinding.ObservableDouble}, and
1075 {@link android.databinding.ObservableParcelable}.
1076 <code>ObservableFields</code> are self-contained observable objects that have a single
1077 field. The primitive versions avoid boxing and unboxing during access operations.
1078 To use, create a public final field in the data class:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001079</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001080
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001081<pre>
George Mount4ba18202015-07-27 12:39:28 -07001082private static class User {
1083 public final ObservableField&lt;String&gt; firstName =
1084 new ObservableField&lt;&gt;();
1085 public final ObservableField&lt;String&gt; lastName =
1086 new ObservableField&lt;&gt;();
1087 public final ObservableInt age = new ObservableInt();
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001088}
1089</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001090<p>
1091 That&apos;s it! To access the value, use the set and get accessor methods:
1092</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001093
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001094<pre>
George Mount4ba18202015-07-27 12:39:28 -07001095user.firstName.set("Google");
1096int age = user.age.get();
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001097</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001098<h3 id="observable_collections">
1099 Observable Collections
1100</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001101
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001102<p>
1103 Some applications use more dynamic structures to hold data. Observable
George Mount4ba18202015-07-27 12:39:28 -07001104 collections allow keyed access to these data objects.
1105 {@link android.databinding.ObservableArrayMap} is
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001106 useful when the key is a reference type, such as String.
1107</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001108
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001109<pre>
George Mount4ba18202015-07-27 12:39:28 -07001110ObservableArrayMap&lt;String, Object&gt; user = new ObservableArrayMap&lt;&gt;();
1111user.put("firstName", "Google");
1112user.put("lastName", "Inc.");
1113user.put("age", 17);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001114</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001115<p>
1116 In the layout, the map may be accessed through the String keys:
1117</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001118
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001119<pre>
George Mount4ba18202015-07-27 12:39:28 -07001120&lt;data&gt;
1121 &lt;import type="android.databinding.ObservableMap"/&gt;
1122 &lt;variable name="user" type="ObservableMap&amp;lt;String, Object&gt;"/&gt;
1123&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001124
George Mount4ba18202015-07-27 12:39:28 -07001125&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001126 android:text=&apos;&commat;{user["lastName"]}&apos;
1127 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001128 android:layout_height="wrap_content"/&gt;
1129&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001130 android:text=&apos;&commat;{String.valueOf(1 + (Integer)user["age"])}&apos;
1131 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001132 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001133</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001134<p>
George Mount4ba18202015-07-27 12:39:28 -07001135 {@link android.databinding.ObservableArrayList} is useful when the key is an integer:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001136</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001137
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001138<pre>
George Mount4ba18202015-07-27 12:39:28 -07001139ObservableArrayList&lt;Object&gt; user = new ObservableArrayList&lt;&gt;();
1140user.add("Google");
1141user.add("Inc.");
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001142user.add(17);
1143</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001144<p>
1145 In the layout, the list may be accessed through the indices:
1146</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001147
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001148<pre>
George Mount4ba18202015-07-27 12:39:28 -07001149&lt;data&gt;
1150 &lt;import type="android.databinding.ObservableList"/&gt;
1151 &lt;import type="com.example.my.app.Fields"/&gt;
1152 &lt;variable name="user" type="ObservableList&amp;lt;Object&gt;"/&gt;
1153&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001154
George Mount4ba18202015-07-27 12:39:28 -07001155&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001156 android:text=&apos;&commat;{user[Fields.LAST_NAME]}&apos;
1157 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001158 android:layout_height="wrap_content"/&gt;
1159&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001160 android:text=&apos;&commat;{String.valueOf(1 + (Integer)user[Fields.AGE])}&apos;
1161 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001162 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001163</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001164<h2 id="generated_binding">
1165 Generated Binding
1166</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001167
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001168<p>
1169 The generated binding class links the layout variables with the Views within
1170 the layout. As discussed earlier, the name and package of the Binding may be
1171 <a href="#custom_binding_class_names">customized</a>. The Generated binding
George Mount4ba18202015-07-27 12:39:28 -07001172 classes all extend {@link android.databinding.ViewDataBinding}.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001173</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001174
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001175<h3 id="creating">
1176 Creating
1177</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001178
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001179<p>
1180 The binding should be created soon after inflation to ensure that the View
1181 hierarchy is not disturbed prior to binding to the Views with expressions
1182 within the layout. There are a few ways to bind to a layout. The most common
1183 is to use the static methods on the Binding class.The inflate method inflates
1184 the View hierarchy and binds to it all it one step. There is a simpler
George Mount4ba18202015-07-27 12:39:28 -07001185 version that only takes a {@link android.view.LayoutInflater} and one that takes a
1186 {@link android.view.ViewGroup} as well:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001187</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001188
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001189<pre>
George Mount4ba18202015-07-27 12:39:28 -07001190MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater);
1191MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001192</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001193<p>
1194 If the layout was inflated using a different mechanism, it may be bound
1195 separately:
1196</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001197
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001198<pre>
George Mount4ba18202015-07-27 12:39:28 -07001199MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001200</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001201<p>
1202 Sometimes the binding cannot be known in advance. In such cases, the binding
George Mount4ba18202015-07-27 12:39:28 -07001203 can be created using the {@link android.databinding.DataBindingUtil} class:
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001204</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001205
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001206<pre>
George Mount4ba18202015-07-27 12:39:28 -07001207ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId,
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001208 parent, attachToParent);
George Mount4ba18202015-07-27 12:39:28 -07001209ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001210</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001211<h3 id="views_with_ids">
1212 Views With IDs
1213</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001214
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001215<p>
1216 A public final field will be generated for each View with an ID in the
1217 layout. The binding does a single pass on the View hierarchy, extracting the
1218 Views with IDs. This mechanism can be faster than calling findViewById for
1219 several Views. For example:
1220</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 -07001223&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"&gt;
1224 &lt;data&gt;
1225 &lt;variable name="user" type="com.example.User"/&gt;
1226 &lt;/data&gt;
1227 &lt;LinearLayout
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001228 android:orientation="vertical"
1229 android:layout_width="match_parent"
George Mount4ba18202015-07-27 12:39:28 -07001230 android:layout_height="match_parent"&gt;
1231 &lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001232 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001233 android:text="&commat;{user.firstName}"
1234 android:id="&commat;+id/firstName"/&gt;
1235 &lt;TextView android:layout_width="wrap_content"
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001236 android:layout_height="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001237 android:text="&commat;{user.lastName}"
1238 android:id="&commat;+id/lastName"/&gt;
1239 &lt;/LinearLayout&gt;
1240&lt;/layout&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001241</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001242<p>
1243 Will generate a binding class with:
1244</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001245
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001246<pre>
George Mount4ba18202015-07-27 12:39:28 -07001247public final TextView firstName;
1248public final TextView lastName;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001249</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001250<p>
1251 IDs are not nearly as necessary as without data binding, but there are still
1252 some instances where access to Views are still necessary from code.
1253</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001254
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001255<h3 id="variables2">
1256 Variables
1257</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001258
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001259<p>
1260 Each variable will be given accessor methods.
1261</p>
1262
1263<pre>
George Mount4ba18202015-07-27 12:39:28 -07001264&lt;data&gt;
1265 &lt;import type="android.graphics.drawable.Drawable"/&gt;
1266 &lt;variable name="user" type="com.example.User"/&gt;
1267 &lt;variable name="image" type="Drawable"/&gt;
1268 &lt;variable name="note" type="String"/&gt;
1269&lt;/data&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001270</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001271<p>
1272 will generate setters and getters in the binding:
1273</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001274
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001275<pre>
George Mount4ba18202015-07-27 12:39:28 -07001276public abstract com.example.User getUser();
1277public abstract void setUser(com.example.User user);
1278public abstract Drawable getImage();
1279public abstract void setImage(Drawable image);
1280public abstract String getNote();
1281public abstract void setNote(String note);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001282</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001283<h3 id="viewstubs">
1284 ViewStubs
1285</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001286
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001287<p>
George Mount4ba18202015-07-27 12:39:28 -07001288 {@link android.view.ViewStub}s are a little different from normal Views. They start off invisible
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001289 and when they either are made visible or are explicitly told to inflate, they
1290 replace themselves in the layout by inflating another layout.
1291</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001292
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001293<p>
George Mount4ba18202015-07-27 12:39:28 -07001294 Because the <code>ViewStub</code> essentially disappears from the View hierarchy, the View
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001295 in the binding object must also disappear to allow collection. Because the
George Mount4ba18202015-07-27 12:39:28 -07001296 Views are final, a {@link android.databinding.ViewStubProxy} object takes the place of the
1297 <code>ViewStub</code>, giving the developer access to the ViewStub when it exists and also
1298 access to the inflated View hierarchy when the <code>ViewStub</code> has been inflated.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001299</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001300
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001301<p>
1302 When inflating another layout, a binding must be established for the new
George Mount4ba18202015-07-27 12:39:28 -07001303 layout. Therefore, the <code>ViewStubProxy</code> must listen to the <code>ViewStub</code>&apos;s
1304 {@link android.view.ViewStub.OnInflateListener} and establish the binding at that time. Since
1305 only one can exist, the <code>ViewStubProxy</code> allows the developer to set an
1306 <code>OnInflateListener</code> on it that it will call after establishing the binding.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001307</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001308
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001309<h3 id="advanced_binding">
1310 Advanced Binding
1311</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001312
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001313<h4 id="dynamic_variables">
1314 Dynamic Variables
1315</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001316
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001317<p>
1318 At times, the specific binding class won&apos;t be known. For example, a
George Mount4ba18202015-07-27 12:39:28 -07001319 {@link android.support.v7.widget.RecyclerView.Adapter} operating against arbitrary layouts
1320 won&apos;t know the specific binding class. It still must assign the binding value during the
1321 {@link android.support.v7.widget.RecyclerView.Adapter#onBindViewHolder}.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001322</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001323
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001324<p>
1325 In this example, all layouts that the RecyclerView binds to have an "item"
George Mount4ba18202015-07-27 12:39:28 -07001326 variable. The <code>BindingHolder</code> has a <code>getBinding</code> method returning the
1327 {@link android.databinding.ViewDataBinding} base.
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<pre>
George Mount4ba18202015-07-27 12:39:28 -07001331public void onBindViewHolder(BindingHolder holder, int position) {
1332 final T item = mItems.get(position);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001333 holder.getBinding().setVariable(BR.item, item);
1334 holder.getBinding().executePendingBindings();
1335}
1336</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001337<h4 id="immediate_binding">
1338 Immediate Binding
1339</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001340
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001341<p>
1342 When a variable or observable changes, the binding will be scheduled to
1343 change before the next frame. There are times, however, when binding must be
1344 executed immediately. To force execution, use the
George Mount4ba18202015-07-27 12:39:28 -07001345 {@link android.databinding.ViewDataBinding#executePendingBindings()} method.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001346</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001347
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001348<h4>
1349 Background Thread
1350</h4>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001351
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001352<p>
1353 You can change your data model in a background thread as long as it is not a
1354 collection. Data binding will localize each variable / field while evaluating
1355 to avoid any concurrency issues.
1356</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001357
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001358<h2 id="attribute_setters">
1359 Attribute Setters
1360</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001361
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001362<p>
1363 Whenever a bound value changes, the generated binding class must call a
1364 setter method on the View with the binding expression. The data binding
1365 framework has ways to customize which method to call to set the value.
1366</p>
1367
1368<h3 id="automatic_setters">
1369 Automatic Setters
1370</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001371For an attribute, data binding tries to find the method setAttribute. The
1372namespace for the attribute does not matter, only the attribute name itself.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001373<p>
1374 For example, an expression associated with TextView&apos;s attribute
1375 <strong><code>android:text</code></strong> will look for a setText(String).
1376 If the expression returns an int, data binding will search for a setText(int)
1377 method. Be careful to have the expression return the correct type, casting if
1378 necessary. Note that data binding will work even if no attribute exists with
1379 the given name. You can then easily "create" attributes for any setter by
1380 using data binding. For example, support DrawerLayout doesn&apos;t have any
1381 attributes, but plenty of setters. You can use the automatic setters to use
1382 one of these.
1383</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001384
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001385<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001386&lt;android.support.v4.widget.<strong>DrawerLayout
1387 android:layout_width="wrap_content"
1388 android:layout_height="wrap_content"
1389 app:scrimColor="&commat;{&commat;color/scrim}"
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001390 app:drawerListener="&commat;{fragment.drawerListener}"/&gt;</strong>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001391</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001392<h3 id="renamed_setters">
1393 Renamed Setters
1394</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001395
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001396<p>
1397 Some attributes have setters that don&apos;t match by name. For these
1398 methods, an attribute may be associated with the setter through
George Mount4ba18202015-07-27 12:39:28 -07001399 {@link android.databinding.BindingMethods} annotation. This must be associated with
1400 a class and contains {@link android.databinding.BindingMethod} annotations, one for
1401 each renamed method. For example, the <strong><code>android:tint</code></strong> attribute
1402 is really associated with {@link android.widget.ImageView#setImageTintList}, not
1403 <code>setTint</code>.
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001404</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001405
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001406<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001407&commat;BindingMethods({
George Mount4ba18202015-07-27 12:39:28 -07001408 &commat;BindingMethod(type = "android.widget.ImageView",
1409 attribute = "android:tint",
1410 method = "setImageTintList"),
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001411})
1412</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001413<p>
1414 It is unlikely that developers will need to rename setters; the android
1415 framework attributes have already been implemented.
1416</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001417
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001418<h3 id="custom_setters">
1419 Custom Setters
1420</h3>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001421
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001422<p>
1423 Some attributes need custom binding logic. For example, there is no
1424 associated setter for the <strong><code>android:paddingLeft</code></strong>
1425 attribute. Instead, <code>setPadding(left, top, right, bottom)</code> exists.
George Mount4ba18202015-07-27 12:39:28 -07001426 A static binding adapter method with the {@link android.databinding.BindingAdapter}
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001427 annotation allows the developer to customize how a setter for an attribute is
1428 called.
1429</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001430
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001431<p>
1432 The android attributes have already had <code>BindingAdapter</code>s created.
1433 For example, here is the one for <code>paddingLeft</code>:
1434</p>
1435
1436<pre>
George Mount4ba18202015-07-27 12:39:28 -07001437&commat;BindingAdapter("android:paddingLeft")
1438public static void setPaddingLeft(View view, int padding) {
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001439 view.setPadding(padding,
1440 view.getPaddingTop(),
1441 view.getPaddingRight(),
1442 view.getPaddingBottom());
1443}
1444</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001445<p>
1446 Binding adapters are useful for other types of customization. For example, a
1447 custom loader can be called off-thread to load an image.
1448</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001449
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001450<p>
1451 Developer-created binding adapters will override the data binding default
1452 adapters when there is a conflict.
1453</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001454
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001455<p>
1456 You can also have adapters that receive multiple parameters.
1457</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001458
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001459<pre>
George Mount4ba18202015-07-27 12:39:28 -07001460&commat;BindingAdapter({"bind:imageUrl", "bind:error"})
1461public static void loadImage(ImageView view, String url, Drawable error) {
1462 Picasso.with(view.getContext()).load(url).error(error).into(view);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001463}
1464</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001465<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001466&lt;ImageView app:imageUrl=“&commat;{venue.imageUrl}”
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001467app:error=“&commat;{&commat;drawable/venueError}”/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001468</pre>
1469
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001470<p>
1471 This adapter will be called if both <strong>imageUrl</strong> and
1472 <strong>error</strong> are used for an ImageView and <em>imageUrl</em> is a
1473 string and <em>error</em> is a drawable.
1474</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001475
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001476<ul>
1477 <li>Custom namespaces are ignored during matching.
1478 </li>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001479
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001480 <li>You can also write adapters for android namespace.
1481 </li>
1482</ul>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001483
George Mount4ba18202015-07-27 12:39:28 -07001484<p>
1485 Binding adapter methods may optionally take the old values in their handlers. A method
1486 taking old and new values should have all old values for the attributes come first, followed
1487 by the new values:
1488</p>
1489<pre>
1490&commat;BindingAdapter("android:paddingLeft")
1491public static void setPaddingLeft(View view, int oldPadding, int newPadding) {
1492 if (oldPadding != newPadding) {
1493 view.setPadding(newPadding,
1494 view.getPaddingTop(),
1495 view.getPaddingRight(),
1496 view.getPaddingBottom());
1497 }
1498}
1499</pre>
1500<p>
1501 Event handlers may only be used with interfaces or abstract classes with one abstract method.
1502 For example:
1503</p>
1504<pre>
1505&commat;BindingAdapter("android:onLayoutChange")
1506public static void setOnLayoutChangeListener(View view, View.OnLayoutChangeListener oldValue,
1507 View.OnLayoutChangeListener newValue) {
1508 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
1509 if (oldValue != null) {
1510 view.removeOnLayoutChangeListener(oldValue);
1511 }
1512 if (newValue != null) {
1513 view.addOnLayoutChangeListener(newValue);
1514 }
1515 }
1516}
1517</pre>
1518<p>
1519 When a listener has multiple methods, it must be split into multiple listeners. For example,
1520 {@link android.view.View.OnAttachStateChangeListener} has two methods:
1521 {@link android.view.View.OnAttachStateChangeListener#onViewAttachedToWindow onViewAttachedToWindow()} and
1522 {@link android.view.View.OnAttachStateChangeListener#onViewDetachedFromWindow onViewDetachedFromWindow()}.
1523 We must then create two interfaces to differentiate the attributes and handlers for them.
1524</p>
1525
1526<pre>
1527&commat;TargetApi(VERSION_CODES.HONEYCOMB_MR1)
1528public interface OnViewDetachedFromWindow {
1529 void onViewDetachedFromWindow(View v);
1530}
1531
1532&commat;TargetApi(VERSION_CODES.HONEYCOMB_MR1)
1533public interface OnViewAttachedToWindow {
1534 void onViewAttachedToWindow(View v);
1535}
1536</pre>
1537<p>
1538 Because changing one listener will also affect the other, we must have three different
1539 binding adapters, one for each attribute and one for both, should they both be set.
1540</p>
1541<pre>
1542&commat;BindingAdapter("android:onViewAttachedToWindow")
1543public static void setListener(View view, OnViewAttachedToWindow attached) {
1544 setListener(view, null, attached);
1545}
1546
1547&commat;BindingAdapter("android:onViewDetachedFromWindow")
1548public static void setListener(View view, OnViewDetachedFromWindow detached) {
1549 setListener(view, detached, null);
1550}
1551
1552&commat;BindingAdapter({"android:onViewDetachedFromWindow", "android:onViewAttachedToWindow"})
1553public static void setListener(View view, final OnViewDetachedFromWindow detach,
1554 final OnViewAttachedToWindow attach) {
1555 if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) {
1556 final OnAttachStateChangeListener newListener;
1557 if (detach == null && attach == null) {
1558 newListener = null;
1559 } else {
1560 newListener = new OnAttachStateChangeListener() {
1561 &commat;Override
1562 public void onViewAttachedToWindow(View v) {
1563 if (attach != null) {
1564 attach.onViewAttachedToWindow(v);
1565 }
1566 }
1567
1568 &commat;Override
1569 public void onViewDetachedFromWindow(View v) {
1570 if (detach != null) {
1571 detach.onViewDetachedFromWindow(v);
1572 }
1573 }
1574 };
1575 }
1576 final OnAttachStateChangeListener oldListener = ListenerUtil.trackListener(view,
1577 newListener, R.id.onAttachStateChangeListener);
1578 if (oldListener != null) {
1579 view.removeOnAttachStateChangeListener(oldListener);
1580 }
1581 if (newListener != null) {
1582 view.addOnAttachStateChangeListener(newListener);
1583 }
1584 }
1585}
1586</pre>
1587<p>
1588 The above example is slightly more complicated than normal because View uses add and remove
1589 for the listener instead of a set method for {@link android.view.View.OnAttachStateChangeListener}.
1590 The <code>android.databinding.adapters.ListenerUtil</code> class helps keep track of the previous
1591 listeners so that they may be removed in the Binding Adaper.
1592</p>
1593<p>
1594 By annotating the interfaces <code>OnViewDetachedFromWindow</code> and
1595 <code>OnViewAttachedToWindow</code> with
1596 <code>&commat;TargetApi(VERSION_CODES.HONEYCOMB_MR1)</code>, the data binding code
1597 generator knows that the listener should only be generated when running on Honeycomb MR1
1598 and new devices, the same version supported by
1599 {@link android.view.View#addOnAttachStateChangeListener}.
1600</p>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001601<h2 id="converters">
1602 Converters
1603</h2>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001604
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001605<h3 id="object_conversions">
1606 Object Conversions
1607</h3>
1608
1609<p>
1610 When an Object is returned from a binding expression, a setter will be chosen
1611 from the automatic, renamed, and custom setters. The Object will be cast to a
1612 parameter type of the chosen setter.
1613</p>
1614
1615<p>
1616 This is a convenience for those using ObservableMaps to hold data. for
1617 example:
1618</p>
1619
1620<pre>
George Mount4ba18202015-07-27 12:39:28 -07001621&lt;TextView
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001622 android:text=&apos;&commat;{userMap["lastName"]}&apos;
1623 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001624 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001625</pre>
1626
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001627<p>
1628The <code>userMap</code> returns an Object and that Object will be automatically cast to
1629 parameter type found in the setter <code>setText(CharSequence)</code>. When there
1630 may be confusion about the parameter type, the developer will need
1631 to cast in the expression.
1632</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001633
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001634<h3 id="custom_conversions">Custom Conversions</h3>
1635
1636<p>
1637 Sometimes conversions should be automatic between specific types. For
1638 example, when setting the background:
1639</p>
1640
1641<pre>
George Mount4ba18202015-07-27 12:39:28 -07001642&lt;View
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001643 android:background="&commat;{isError ? &commat;color/red : &commat;color/white}"
1644 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001645 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001646</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001647<p>
1648 Here, the background takes a <code>Drawable</code>, but the color is an
1649 integer. Whenever a <code>Drawable</code> is expected and an integer is
1650 returned, the <code>int</code> should be converted to a
1651 <code>ColorDrawable</code>. This conversion is done using a static method
1652 with a BindingConversion annotation:
1653</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001654
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001655<pre>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001656&commat;BindingConversion
George Mount4ba18202015-07-27 12:39:28 -07001657public static ColorDrawable convertColorToDrawable(int color) {
1658 return new ColorDrawable(color);
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001659}
1660</pre>
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001661<p>
1662 Note that conversions only happen at the setter level, so it is <strong>not
1663 allowed</strong> to mix types like this:
1664</p>
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001665
Dirk Doughertyea1f6fb2015-05-26 20:31:12 -07001666<pre>
George Mount4ba18202015-07-27 12:39:28 -07001667&lt;View
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001668 android:background="&commat;{isError ? &commat;drawable/error : &commat;color/white}"
1669 android:layout_width="wrap_content"
George Mount4ba18202015-07-27 12:39:28 -07001670 android:layout_height="wrap_content"/&gt;
Dirk Dougherty493ff3c2015-05-26 16:52:23 -07001671</pre>