1page.title=Data Binding Library 2page.metaDescription=The Data Binding Library enables you to write declarative layouts. 3page.tags="databinding", "layouts" 4@jd:body 5 6<div id="qv-wrapper"> 7 <div id="qv"> 8 <h2> 9 In this document: 10 </h2> 11 12 <ol> 13 <li> 14 <a href="#build_environment">Build Environment</a> 15 </li> 16 17 <li> 18 <a href="#data_binding_layout_files">Data Binding Layout Files</a> 19 <ol> 20 <li> 21 <a href="#writing_expressions">Writing your first set of data binding 22 expressions</a> 23 </li> 24 25 <li> 26 <a href="#data_object">Data Object</a> 27 </li> 28 29 <li> 30 <a href="#binding_data">Binding Data</a> 31 </li> 32 <li> 33 <a href="#event_handling">Event Handling</a> 34 <ol> 35 <li> 36 <a href="#method_references">Method References</a> 37 </li> 38 <li> 39 <a href="#listener_bindings">Listener Bindings</a> 40 </li> 41 </ol> 42 </li> 43 </ol> 44 </li> 45 46 <li> 47 <a href="#layout_details">Layout Details</a> 48 <ol> 49 <li> 50 <a href="#imports">Imports</a> 51 </li> 52 53 <li> 54 <a href="#variables">Variables</a> 55 </li> 56 57 <li> 58 <a href="#custom_binding_class_names">Custom Binding Class Names</a> 59 </li> 60 61 <li> 62 <a href="#includes">Includes</a> 63 </li> 64 65 <li> 66 <a href="#expression_language">Expression Language</a> 67 </li> 68 </ol> 69 </li> 70 71 <li> 72 <a href="#data_objects">Data Objects</a> 73 <ol> 74 <li> 75 <a href="#observable_objects">Observable Objects</a> 76 </li> 77 78 <li> 79 <a href="#observablefields">ObservableFields</a> 80 </li> 81 82 <li> 83 <a href="#observable_collections">Observable Collections</a> 84 </li> 85 </ol> 86 </li> 87 88 <li> 89 <a href="#generated_binding">Generated Binding</a> 90 <ol> 91 <li> 92 <a href="#creating">Creating</a> 93 </li> 94 95 <li> 96 <a href="#views_with_ids">Views With IDs</a> 97 </li> 98 99 <li> 100 <a href="#variables">Variables</a> 101 </li> 102 103 <li> 104 <a href="#viewstubs">ViewStubs</a> 105 </li> 106 107 <li> 108 <a href="#advanced_binding">Advanced Binding</a> 109 </li> 110 </ol> 111 </li> 112 113 <li> 114 <a href="#attribute_setters">Attribute Setters</a> 115 <ol> 116 <li> 117 <a href="#automatic_setters">Automatic Setters</a> 118 </li> 119 120 <li> 121 <a href="#renamed_setters">Renamed Setters</a> 122 </li> 123 124 <li> 125 <a href="#custom_setters">Custom Setters</a> 126 </li> 127 </ol> 128 </li> 129 130 <li> 131 <a href="#converters">Converters</a> 132 <ol> 133 <li> 134 <a href="#object_conversions">Object Conversions</a> 135 </li> 136 137 <li> 138 <a href="#custom_conversions">Custom Conversions</a> 139 </li> 140 </ol> 141 </li> 142 143 <li> 144 <a href="#studio_support">Android Studio Support for Data Binding</a> 145 </li> 146 147 </ol> 148 </div><!-- qv --> 149</div><!-- qv-wrapper --> 150 151<p> 152 This document explains how to use the Data Binding Library to write 153 declarative layouts and minimize the glue code necessary to bind your 154 application logic and layouts. 155</p> 156 157<p> 158 The Data Binding Library offers both flexibility and broad compatibility — 159 it's a support library, so you can use it with all Android platform versions 160 back to <strong>Android 2.1</strong> (API level 7+). 161</p> 162 163<p> 164 To use data binding, Android Plugin for Gradle <strong>1.5.0-alpha1</strong> 165 or higher is required. 166</p> 167 168<h2 id="build_environment"> 169 Build Environment 170</h2> 171 172<p> 173 To get started with Data Binding, download the library from the Support 174 repository in the Android SDK manager. 175</p> 176 177<p> 178 To configure your app to use data binding, add the <code>dataBinding</code> 179 element to your <code>build.gradle</code> file in the app module. 180</p> 181 182<p> 183 Use the following code snippet to configure data binding: 184</p> 185<pre> 186android { 187 .... 188 dataBinding { 189 enabled = true 190 } 191} 192</pre> 193<p> 194 If you have an app module that depends on a library which uses data binding, 195 your app module must configure data binding in its <code>build.gradle</code> 196 file as well. 197</p> 198 199<p> 200 Also, make sure you are using a compatible version of Android Studio. 201 <strong>Android Studio 1.3</strong> and later provides support for data 202 binding as described in <a href="#studio_support">Android Studio Support for 203 Data Binding</a>. 204</p> 205 206<h2 id="data_binding_layout_files"> 207 Data Binding Layout Files 208</h2> 209 210<h3 id="writing_expressions"> 211 Writing your first set of data binding expressions 212</h3> 213 214<p> 215 Data-binding layout files are slightly different and start with a root tag of 216 <strong>layout</strong> followed by a <strong>data</strong> element and a 217 <strong>view</strong> root element. This view element is what your root would 218 be in a non-binding layout file. A sample file looks like this: 219</p> 220 221<pre> 222<?xml version="1.0" encoding="utf-8"?> 223<layout xmlns:android="http://schemas.android.com/apk/res/android"> 224 <data> 225 <variable name="user" type="com.example.User"/> 226 </data> 227 <LinearLayout 228 android:orientation="vertical" 229 android:layout_width="match_parent" 230 android:layout_height="match_parent"> 231 <TextView android:layout_width="wrap_content" 232 android:layout_height="wrap_content" 233 android:text="@{user.firstName}"/> 234 <TextView android:layout_width="wrap_content" 235 android:layout_height="wrap_content" 236 android:text="@{user.lastName}"/> 237 </LinearLayout> 238</layout> 239</pre> 240<p> 241 The user <strong>variable</strong> within <strong>data</strong> describes a 242 property that may be used within this layout. 243</p> 244<pre> 245<<strong>variable name="user" type="com.example.User"</strong>/> 246</pre> 247<p> 248 Expressions within the layout are written in the attribute properties using 249 the “<code>&commat;{}</code>” syntax. Here, the TextView’s text is set to 250 the firstName property of user: 251</p> 252 253<pre> 254<TextView android:layout_width="wrap_content" 255 android:layout_height="wrap_content" 256 android:text="&commat;{user.firstName}"/> 257</pre> 258<h3 id="data_object"> 259 Data Object 260</h3> 261 262<p> 263 Let’s assume for now that you have a plain-old Java object (POJO) for User: 264</p> 265 266<pre> 267public class User { 268 public final String firstName; 269 public final String lastName; 270 public User(String firstName, String lastName) { 271 this.firstName = firstName; 272 this.lastName = lastName; 273 } 274} 275</pre> 276<p> 277 This type of object has data that never changes. It is common in applications 278 to have data that is read once and never changes thereafter. It is also 279 possible to use a JavaBeans objects: 280</p> 281<pre> 282public class User { 283 private final String firstName; 284 private final String lastName; 285 public User(String firstName, String lastName) { 286 this.firstName = firstName; 287 this.lastName = lastName; 288 } 289 public String getFirstName() { 290 return this.firstName; 291 } 292 public String getLastName() { 293 return this.lastName; 294 } 295} 296</pre> 297<p> 298 From the perspective of data binding, these two classes are equivalent. The 299 expression <strong><code>&commat;{user.firstName}</code></strong> used 300 for the TextView’s <strong><code>android:text</code></strong> attribute will 301 access the <strong><code>firstName</code></strong> field in the former class 302 and the <code>getFirstName()</code> method in the latter class. 303 Alternatively, it will also be resolved to <code>firstName()</code> if that 304 method exists. 305</p> 306 307<h3 id="binding_data"> 308 Binding Data 309</h3> 310 311<p> 312 By default, a Binding class will be generated based on the name of the layout 313 file, converting it to Pascal case and suffixing “Binding” to it. The above 314 layout file was <code>main_activity.xml</code> so the generate class was 315 <code>MainActivityBinding</code>. This class holds all the bindings from the 316 layout properties (e.g. the <code>user</code> variable) to the layout’s Views 317 and knows how to assign values for the binding expressions.The easiest means 318 for creating the bindings is to do it while inflating: 319</p> 320 321<pre> 322@Override 323protected void onCreate(Bundle savedInstanceState) { 324 super.onCreate(savedInstanceState); 325 MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity); 326 User user = new User("Test", "User"); 327 binding.setUser(user); 328} 329</pre> 330<p> 331 You’re done! Run the application and you’ll see Test User in the UI. 332 Alternatively, you can get the view via: 333</p> 334 335<pre> 336MainActivityBinding binding = MainActivityBinding.<em>inflate</em>(getLayoutInflater()); 337</pre> 338<p> 339 If you are using data binding items inside a ListView or RecyclerView 340 adapter, you may prefer to use: 341</p> 342 343<pre> 344ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false); 345//or 346ListItemBinding binding = DataBindingUtil.<em>inflate</em>(layoutInflater, R.layout.<em><strong>list_item</strong></em>, viewGroup, <strong>false</strong>); 347</pre> 348<h3 id="event_handling">Event Handling</h3> 349<p> 350Data Binding allows you to write expressions handling events that are dispatched from the views (e.g. onClick). 351Event attribute names are governed by the name of the listener method with a few exceptions. 352For example, {@link android.view.View.OnLongClickListener} has a method {@link android.view.View.OnLongClickListener#onLongClick onLongClick()}, 353so the attribute for this event is <code>android:onLongClick</code>. 354There are two ways to handle an event. 355</p> 356<ul> 357 <li> 358 <a href="#method_references">Method References</a>: In your expressions, you can reference methods that conform to the signature of the listener method. When an expression evaluates to a method reference, Data Binding wraps the method reference and owner object in a listener, and sets that listener on the target view. If the expression evaluates to null, Data Binding does not create a listener and sets a null listener instead. 359 </li> 360 <li> 361 <a href="#listener_bindings">Listener Bindings</a>: These are lambda expressions that are evaluated when the event happens. 362Data Binding always creates a listener, which it sets on the view. When the event is dispatched, the listener evaluates the lambda expression. 363 </li> 364</ul> 365<h4 id="method_references"> 366 Method References 367</h4> 368<p> 369 Events can be bound to handler methods directly, similar to the way 370 <strong><code>android:onClick</code></strong> can be assigned to a method in an Activity. 371 One major advantage compared to the {@code View#onClick} attribute is that the expression 372 is processed at compile time, so if the method does not exist or its signature is not 373 correct, you receive a compile time error.</p> 374<p> 375 The major difference between Method References and Listener Bindings is that 376 the actual listener implementation is created when the data is bound, not 377 when the event is triggered. If you prefer to evaluate the expression when 378 the event happens, you should use <a href="#listener_bindings">listener 379 binding</a>. 380</p> 381<p> 382 To assign an event to its handler, use a normal binding expression, with the value 383 being the method name to call. For example, if your data object has two methods: 384</p> 385<pre>public class MyHandlers { 386 public void onClickFriend(View view) { ... } 387} 388</pre> 389<p> 390 The binding expression can assign the click listener for a View: 391</p> 392<pre> 393<?xml version="1.0" encoding="utf-8"?> 394<layout xmlns:android="http://schemas.android.com/apk/res/android"> 395 <data> 396 <variable name="handlers" type="com.example.Handlers"/> 397 <variable name="user" type="com.example.User"/> 398 </data> 399 <LinearLayout 400 android:orientation="vertical" 401 android:layout_width="match_parent" 402 android:layout_height="match_parent"> 403 <TextView android:layout_width="wrap_content" 404 android:layout_height="wrap_content" 405 android:text="@{user.firstName}" 406 android:onClick="@{handlers::onClickFriend}"/> 407 </LinearLayout> 408</layout> 409</pre> 410<p> 411Note that the signature of the method in the expression must exactly match the signature of the method in the 412Listener object. 413</p> 414<h4 id="listener_bindings"> 415 Listener Bindings 416</h4> 417<p> 418 Listener Bindings are binding expressions that run when an event happens. 419 They are similar to method references, but they let you run arbitrary data 420 binding expressions. This feature is available with Android Gradle Plugin for Gradle 421 version 2.0 and later. 422</p> 423<p> 424 In method references, the parameters of the method must 425 match the parameters of the event listener. In Listener Bindings, only your 426 return value must match the expected return value of the listener (unless it 427 is expecting void). 428 For example, you can have a presenter class that has the following method: 429</p> 430<pre> 431public class Presenter { 432 public void onSaveClick(Task task){} 433} 434</pre> 435 Then you can bind the click event to your class as follows: 436<pre> 437 <?xml version="1.0" encoding="utf-8"?> 438 <layout xmlns:android="http://schemas.android.com/apk/res/android"> 439 <data> 440 <variable name="task" type="com.android.example.Task" /> 441 <variable name="presenter" type="com.android.example.Presenter" /> 442 </data> 443 <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> 444 <Button android:layout_width="wrap_content" android:layout_height="wrap_content" 445 android:onClick="@{() -> presenter.onSaveClick(task)}" /> 446 </LinearLayout> 447 </layout> 448</pre> 449<p> 450 Listeners are represented by lambda expressions that are allowed only as root 451 elements of your expressions. When a callback is used in an expression, Data 452 Binding automatically creates the necessary listener and registers for the 453 event. When the view fires the event, Data Binding evaluates the given 454 expression. As in regular binding expressions, you still get the null and 455 thread safety of Data Binding while these listener expressions are being 456 evaluated. 457</p> 458<p> 459 Note that in the example above, we haven't defined the {@code view} parameter 460 that is passed into {@link 461 android.view.View.OnClickListener#onClick(android.view.View view)}. Listener 462 bindings provide two choices for listener parameters: you can either ignore 463 all parameters to the method or name all of them. If you prefer to name the 464 parameters, you can use them in your expression. For example, the expression 465 above could be written as: 466</p> 467<pre> 468 android:onClick="@{(view) -> presenter.onSaveClick(task)}" 469</pre> 470Or if you wanted to use the parameter in the expression, it could work as follows: 471<pre> 472public class Presenter { 473 public void onSaveClick(View view, Task task){} 474} 475</pre> 476<pre> 477 android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}" 478</pre> 479You can use a lambda expression with more than one parameter: 480<pre> 481public class Presenter { 482 public void onCompletedChanged(Task task, boolean completed){} 483} 484</pre> 485<pre> 486 <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" 487 android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" /> 488</pre> 489<p> 490 If the event you are listening to returns a value whose type is not {@code 491 void}, your expressions must return the same type of value as well. For 492 example, if you want to listen for the long click event, your expression 493 should return {@code boolean}. 494</p> 495<pre> 496public class Presenter { 497 public boolean onLongClick(View view, Task task){} 498} 499</pre> 500<pre> 501 android:onLongClick="@{(theView) -> presenter.onLongClick(theView, task)}" 502</pre> 503<p> 504If the expression cannot be evaluated due to {@code null} objects, Data Binding returns 505the default Java value for that type. For example, {@code null} for reference types, {@code 0} for {@code int}, 506{@code false} for {@code boolean}, etc. 507</p> 508<p> 509If you need to use an expression with a predicate (e.g. ternary), you can use 510{@code void} as a symbol. 511</p> 512<pre> 513 android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}" 514</pre> 515 516<h5>Avoid Complex Listeners</h5> 517Listener expressions are very powerful and can make your code very easy to read. 518On the other hand, listeners containing complex expressions make your layouts hard to read and unmaintainable. 519These expressions should be as simple as passing available data from your UI to your callback method. You should implement 520any business logic inside the callback method that you invoked from the listener expression. 521 522<p> 523 Some specialized click event handlers exist and they need an attribute other than 524 <code>android:onClick</code> to avoid a conflict. The following attributes have been created 525 to avoid such conflicts: 526</p> 527 528<table> 529 <tr> 530 <th>Class</th> 531 <th>Listener Setter</th> 532 <th>Attribute</th> 533 </tr> 534 <tr> 535 <td>{@link android.widget.SearchView}</td> 536 <td>{@link android.widget.SearchView#setOnSearchClickListener}</td> 537 <td><code>android:onSearchClick</code></td> 538 </tr> 539 <tr> 540 <td>{@link android.widget.ZoomControls}</td> 541 <td>{@link android.widget.ZoomControls#setOnZoomInClickListener}</td> 542 <td><code>android:onZoomIn</code></td> 543 </tr> 544 <tr> 545 <td>{@link android.widget.ZoomControls}</td> 546 <td>{@link android.widget.ZoomControls#setOnZoomOutClickListener}</td> 547 <td><code>android:onZoomOut</code></td> 548 </tr> 549</table> 550 551<h2 id="layout_details"> 552 Layout Details 553</h2> 554 555<h3 id="imports"> 556 Imports 557</h3> 558 559<p> 560 Zero or more <strong><code>import</code></strong> elements may be used inside 561 the <strong><code>data</code></strong> element. These allow easy reference to 562 classes inside your layout file, just like in Java. 563</p> 564 565<pre> 566<data> 567 <import type="android.view.View"/> 568</data> 569</pre> 570<p> 571 Now, View may be used within your binding expression: 572</p> 573 574<pre> 575<TextView 576 android:text="@{user.lastName}" 577 android:layout_width="wrap_content" 578 android:layout_height="wrap_content" 579 android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/> 580</pre> 581<p> 582 When there are class name conflicts, one of the classes may be renamed to an 583 “alias:” 584</p> 585 586<pre> 587<import type="android.view.View"/> 588<import type="com.example.real.estate.View" 589 alias="Vista"/> 590</pre> 591<p> 592 Now, <strong><code>Vista</code></strong> may be used to reference the 593 <code>com.example.real.estate.View</code> and 594 <strong><code>View</code></strong> may be used to reference 595 <code>android.view.View</code> within the layout file. Imported types may be 596 used as type references in variables and expressions: 597</p> 598 599<pre> 600<data> 601 <import type="com.example.User"/> 602 <import type="java.util.List"/> 603 <variable name="user" type="User"/> 604 <variable name="userList" type="List&lt;User>"/> 605</data> 606</pre> 607<p class="caution"> 608 <strong>Note</strong>: Android Studio does not yet handle imports so the 609 autocomplete for imported variables may not work in your IDE. Your 610 application will still compile fine and you can work around the IDE issue by 611 using fully qualified names in your variable definitions. 612</p> 613 614<pre> 615<TextView 616 android:text="@{((User)(user.connection)).lastName}" 617 android:layout_width="wrap_content" 618 android:layout_height="wrap_content"/> 619</pre> 620<p> 621 Imported types may also be used when referencing static fields and methods in 622 expressions: 623</p> 624 625<pre> 626<data> 627 <import type="com.example.MyStringUtils"/> 628 <variable name="user" type="com.example.User"/> 629</data> 630… 631<TextView 632 android:text="@{MyStringUtils.capitalize(user.lastName)}" 633 android:layout_width="wrap_content" 634 android:layout_height="wrap_content"/> 635</pre> 636<p> 637 Just as in Java, <code>java.lang.*</code> is imported automatically. 638</p> 639 640<h3 id="variables"> 641 Variables 642</h3> 643 644<p> 645 Any number of <strong><code>variable</code></strong> elements may be used 646 inside the <strong><code>data</code></strong> element. Each 647 <strong><code>variable</code></strong> element describes a property that may 648 be set on the layout to be used in binding expressions within the layout 649 file. 650</p> 651 652<pre> 653<data> 654 <import type="android.graphics.drawable.Drawable"/> 655 <variable name="user" type="com.example.User"/> 656 <variable name="image" type="Drawable"/> 657 <variable name="note" type="String"/> 658</data> 659</pre> 660<p> 661 The variable types are inspected at compile time, so if a variable implements 662 {@link android.databinding.Observable} or is an <a href= 663 "#observable_collections">observable collection</a>, that should be reflected 664 in the type. If the variable is a base class or interface that does not 665 implement the Observable* interface, the variables will <strong>not 666 be</strong> observed! 667</p> 668 669<p> 670 When there are different layout files for various configurations (e.g. 671 landscape or portrait), the variables will be combined. There must not be 672 conflicting variable definitions between these layout files. 673</p> 674 675<p> 676 The generated binding class will have a setter and getter for each of the 677 described variables. The variables will take the default Java values until 678 the setter is called — <code>null</code> for reference types, 679 <code>0</code> for <code>int</code>, <code>false</code> for 680 <code>boolean</code>, etc. 681</p> 682 683<p> 684 A special variable named <code>context</code> is generated for use in binding 685 expressions as needed. The value for <code>context</code> is the 686 <code>Context</code> from the root View's {@link android.view.View#getContext}. 687 The <code>context</code> variable will be overridden by an explicit variable 688 declaration with that name. 689</p> 690 691<h3 id="custom_binding_class_names"> 692 Custom Binding Class Names 693</h3> 694 695<p> 696 By default, a Binding class is generated based on the name of the layout 697 file, starting it with upper-case, removing underscores ( _ ) and 698 capitalizing the following letter and then suffixing “Binding”. This class 699 will be placed in a databinding package under the module package. For 700 example, the layout file <code>contact_item.xml</code> will generate 701 <code>ContactItemBinding</code>. If the module package is 702 <code>com.example.my.app</code>, then it will be placed in 703 <code>com.example.my.app.databinding</code>. 704</p> 705 706<p> 707 Binding classes may be renamed or placed in different packages by adjusting 708 the <strong><code>class</code></strong> attribute of the 709 <strong><code>data</code></strong> element. For example: 710</p> 711 712<pre> 713<data class="ContactItem"> 714 ... 715</data> 716</pre> 717<p> 718 This generates the binding class as <code>ContactItem</code> in the 719 databinding package in the module package. If the class should be generated 720 in a different package within the module package, it may be prefixed with 721 “.”: 722</p> 723 724<pre> 725<data class=".ContactItem"> 726 ... 727</data> 728</pre> 729<p> 730 In this case, <code>ContactItem</code> is generated in the module package 731 directly. Any package may be used if the full package is provided: 732</p> 733 734<pre> 735<data class="com.example.ContactItem"> 736 ... 737</data> 738</pre> 739<h3 id="includes"> 740 Includes 741</h3> 742 743<p> 744 Variables may be passed into an included layout's binding from the 745 containing layout by using the application namespace and the variable name in 746 an attribute: 747</p> 748 749<pre> 750<?xml version="1.0" encoding="utf-8"?> 751<layout xmlns:android="http://schemas.android.com/apk/res/android" 752 xmlns:bind="http://schemas.android.com/apk/res-auto"> 753 <data> 754 <variable name="user" type="com.example.User"/> 755 </data> 756 <LinearLayout 757 android:orientation="vertical" 758 android:layout_width="match_parent" 759 android:layout_height="match_parent"> 760 <include layout="@layout/name" 761 bind:user="@{user}"/> 762 <include layout="@layout/contact" 763 bind:user="@{user}"/> 764 </LinearLayout> 765</layout> 766</pre> 767<p> 768 Here, there must be a <code>user</code> variable in both the 769 <code>name.xml</code> and <code>contact.xml</code> layout files. 770</p> 771<p> 772 Data binding does not support include as a direct child of a merge element. For example, 773 <strong>the following layout is not supported:</strong> 774</p> 775<pre> 776<?xml version="1.0" encoding="utf-8"?> 777<layout xmlns:android="http://schemas.android.com/apk/res/android" 778 xmlns:bind="http://schemas.android.com/apk/res-auto"> 779 <data> 780 <variable name="user" type="com.example.User"/> 781 </data> 782 <merge> 783 <include layout="@layout/name" 784 bind:user="@{user}"/> 785 <include layout="@layout/contact" 786 bind:user="@{user}"/> 787 </merge> 788</layout> 789</pre> 790<h3 id="expression_language"> 791 Expression Language 792</h3> 793 794<h4 id="common_features"> 795 Common Features 796</h4> 797 798<p> 799 The expression language looks a lot like a Java expression. These are the 800 same: 801</p> 802 803<ul> 804 <li>Mathematical <strong><code>+ - / * %</code></strong> 805 </li> 806 807 <li>String concatenation <strong><code>+</code></strong> 808 </li> 809 810 <li> 811 Logical <strong><code>&& ||</code></strong> 812 </li> 813 814 <li>Binary <strong><code>& | ^</code></strong> 815 </li> 816 817 <li>Unary <strong><code>+ - ! ~</code></strong> 818 </li> 819 820 <li>Shift <strong><code>>> >>> <<</code></strong> 821 </li> 822 823 <li>Comparison <strong><code>== > < >= <=</code></strong> 824 </li> 825 826 <li> 827 <strong><code>instanceof</code></strong> 828 </li> 829 830 <li>Grouping <strong><code>()</code></strong> 831 </li> 832 833 <li>Literals - character, String, numeric, <strong><code>null</code></strong> 834 </li> 835 836 <li>Cast 837 </li> 838 839 <li>Method calls 840 </li> 841 842 <li>Field access 843 </li> 844 845 <li>Array access <strong><code>[]</code></strong> 846 </li> 847 848 <li>Ternary operator <strong><code>?:</code></strong> 849 </li> 850</ul> 851 852<p> 853 Examples: 854</p> 855 856<pre> 857android:text="@{String.valueOf(index + 1)}" 858android:visibility="@{age &lt; 13 ? View.GONE : View.VISIBLE}" 859android:transitionName='@{"image_" + id}' 860</pre> 861<h4 id="missing_operations"> 862 Missing Operations 863</h4> 864 865<p> 866 A few operations are missing from the expression syntax that you can use in 867 Java. 868</p> 869 870<ul> 871 <li> 872 <strong><code>this</code></strong> 873 </li> 874 875 <li> 876 <strong><code>super</code></strong> 877 </li> 878 879 <li> 880 <strong><code>new</code></strong> 881 </li> 882 883 <li>Explicit generic invocation 884 </li> 885</ul> 886 887<h4 id="null_coalescing_operator"> 888 Null Coalescing Operator 889</h4> 890 891<p> 892 The null coalescing operator (<strong><code>??</code></strong>) chooses the 893 left operand if it is not null or the right if it is null. 894</p> 895 896<pre> 897<strong>android:text="@{user.displayName ?? user.lastName}"</strong> 898</pre> 899<p> 900 This is functionally equivalent to: 901</p> 902 903<pre> 904<strong>android:text="@{user.displayName != null ? user.displayName : user.lastName}"</strong> 905</pre> 906<h4 id="property_reference"> 907 Property Reference 908</h4> 909 910<p> 911 The first was already discussed in the <a href= 912 "#writing_your_first_data_binding_expressions">Writing your first data 913 binding expressions</a> above: short form JavaBean references. When an 914 expression references a property on a class, it uses the same format for 915 fields, getters, and ObservableFields. 916</p> 917 918<pre> 919<strong>android:text="@{user.lastName}"</strong> 920</pre> 921<h4> 922 Avoiding NullPointerException 923</h4> 924 925<p> 926 Generated data binding code automatically checks for nulls and avoid null 927 pointer exceptions. For example, in the expression 928 <code>@{user.name}</code>, if <code>user</code> is null, 929 <code>user.name</code> will be assigned its default value (null). If you were 930 referencing <code>user.age</code>, where age is an <code>int</code>, then it 931 would default to 0. 932</p> 933 934<h4 id="collections"> 935 Collections 936</h4> 937 938<p> 939 Common collections: arrays, lists, sparse lists, and maps, may be accessed 940 using the <code>[]</code> operator for convenience. 941</p> 942 943<pre> 944<data> 945 <import type="android.util.SparseArray"/> 946 <import type="java.util.Map"/> 947 <import type="java.util.List"/> 948 <variable name="list" type="List&lt;String>"/> 949 <variable name="sparse" type="SparseArray&lt;String>"/> 950 <variable name="map" type="Map&lt;String, String>"/> 951 <variable name="index" type="int"/> 952 <variable name="key" type="String"/> 953</data> 954… 955android:text="@{list[index]}" 956… 957android:text="@{sparse[index]}" 958… 959android:text="@{map[key]}" 960 961</pre> 962<h4 id="string_literals"> 963 String Literals 964</h4> 965 966<p> 967 When using single quotes around the attribute value, it is easy to use double 968 quotes in the expression: 969</p> 970 971<pre> 972android:text='@{map["firstName"]}' 973</pre> 974<p> 975 It is also possible to use double quotes to surround the attribute value. 976 When doing so, String literals should either use the &quot; or back quote 977 (`). 978</p> 979 980<pre> 981android:text="@{map[`firstName`}" 982android:text="@{map[&quot;firstName&quot;]}" 983</pre> 984<h4 id="resources"> 985 Resources 986</h4> 987 988<p> 989 It is possible to access resources as part of expressions using the normal 990 syntax: 991</p> 992 993<pre> 994android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}" 995</pre> 996<p> 997 Format strings and plurals may be evaluated by providing parameters: 998</p> 999 1000<pre> 1001android:text="@{@string/nameFormat(firstName, lastName)}" 1002android:text="@{@plurals/banana(bananaCount)}" 1003</pre> 1004<p> 1005 When a plural takes multiple parameters, all parameters should be passed: 1006</p> 1007 1008<pre> 1009 1010 Have an orange 1011 Have %d oranges 1012 1013android:text="@{@plurals/orange(orangeCount, orangeCount)}" 1014</pre> 1015<p> 1016 Some resources require explicit type evaluation. 1017</p> 1018 1019<table> 1020 <tr> 1021 <th> 1022 Type 1023 </th> 1024 <th> 1025 Normal Reference 1026 </th> 1027 <th> 1028 Expression Reference 1029 </th> 1030 </tr> 1031 1032 <tr> 1033 <td> 1034 String[] 1035 </td> 1036 <td> 1037 @array 1038 </td> 1039 <td> 1040 @stringArray 1041 </td> 1042 </tr> 1043 1044 <tr> 1045 <td> 1046 int[] 1047 </td> 1048 <td> 1049 @array 1050 </td> 1051 <td> 1052 @intArray 1053 </td> 1054 </tr> 1055 1056 <tr> 1057 <td> 1058 TypedArray 1059 </td> 1060 <td> 1061 @array 1062 </td> 1063 <td> 1064 @typedArray 1065 </td> 1066 </tr> 1067 1068 <tr> 1069 <td> 1070 Animator 1071 </td> 1072 <td> 1073 @animator 1074 </td> 1075 <td> 1076 @animator 1077 </td> 1078 </tr> 1079 1080 <tr> 1081 <td> 1082 StateListAnimator 1083 </td> 1084 <td> 1085 @animator 1086 </td> 1087 <td> 1088 @stateListAnimator 1089 </td> 1090 </tr> 1091 1092 <tr> 1093 <td> 1094 color <code>int</code> 1095 </td> 1096 <td> 1097 @color 1098 </td> 1099 <td> 1100 @color 1101 </td> 1102 </tr> 1103 1104 <tr> 1105 <td> 1106 ColorStateList 1107 </td> 1108 <td> 1109 @color 1110 </td> 1111 <td> 1112 @colorStateList 1113 </td> 1114 </tr> 1115</table> 1116 1117<h2 id="data_objects"> 1118 Data Objects 1119</h2> 1120 1121<p> 1122 Any plain old Java object (POJO) may be used for data binding, but modifying 1123 a POJO will not cause the UI to update. The real power of data binding can be 1124 used by giving your data objects the ability to notify when data changes. 1125 There are three different data change notification mechanisms, 1126 <a href="#observable_objects">Observable objects</a>, 1127 <a href="#observablefields">observable fields</a>, and 1128 <a href="#observable_collections">observable collection</a>s. 1129</p> 1130 1131<p> 1132 When one of these observable data object is bound to the UI and a property of 1133 the data object changes, the UI will be updated automatically. 1134</p> 1135 1136<h3 id="observable_objects"> 1137 Observable Objects 1138</h3> 1139 1140<p> 1141 A class implementing the {@link android.databinding.Observable} interface 1142 will allow the binding to attach a single listener to a bound object to 1143 listen for changes of all properties on that object. 1144</p> 1145 1146<p> 1147 The {@link android.databinding.Observable} interface has a mechanism to add and remove 1148 listeners, but notifying is up to the developer. To make development easier, 1149 a base class, {@link android.databinding.BaseObservable}, was created to implement the 1150 listener registration mechanism. The data class implementer is still 1151 responsible for notifying when the properties change. This is done by 1152 assigning a {@link android.databinding.Bindable} annotation to the getter and notifying in 1153 the setter. 1154</p> 1155 1156<pre> 1157private static class User extends BaseObservable { 1158 private String firstName; 1159 private String lastName; 1160 @Bindable 1161 public String getFirstName() { 1162 return this.firstName; 1163 } 1164 @Bindable 1165 public String getLastName() { 1166 return this.lastName; 1167 } 1168 public void setFirstName(String firstName) { 1169 this.firstName = firstName; 1170 notifyPropertyChanged(BR.firstName); 1171 } 1172 public void setLastName(String lastName) { 1173 this.lastName = lastName; 1174 notifyPropertyChanged(BR.lastName); 1175 } 1176} 1177</pre> 1178<p> 1179 The {@link android.databinding.Bindable} annotation generates an entry in the BR class file 1180 during compilation. The BR class file will be generated in the module 1181 package. If the base class for data classes cannot be changed, the 1182 {@link android.databinding.Observable} interface may be implemented using the convenient 1183 {@link android.databinding.PropertyChangeRegistry} to store and notify listeners 1184 efficiently. 1185</p> 1186 1187<h3 id="observablefields"> 1188 ObservableFields 1189</h3> 1190 1191<p> 1192 A little work is involved in creating {@link android.databinding.Observable} classes, so 1193 developers who want to save time or have few properties may use 1194 {@link android.databinding.ObservableField} and its siblings 1195 {@link android.databinding.ObservableBoolean}, 1196 {@link android.databinding.ObservableByte}, 1197 {@link android.databinding.ObservableChar}, 1198 {@link android.databinding.ObservableShort}, 1199 {@link android.databinding.ObservableInt}, 1200 {@link android.databinding.ObservableLong}, 1201 {@link android.databinding.ObservableFloat}, 1202 {@link android.databinding.ObservableDouble}, and 1203 {@link android.databinding.ObservableParcelable}. 1204 <code>ObservableFields</code> are self-contained observable objects that have a single 1205 field. The primitive versions avoid boxing and unboxing during access operations. 1206 To use, create a public final field in the data class: 1207</p> 1208 1209<pre> 1210private static class User { 1211 public final ObservableField<String> firstName = 1212 new ObservableField<>(); 1213 public final ObservableField<String> lastName = 1214 new ObservableField<>(); 1215 public final ObservableInt age = new ObservableInt(); 1216} 1217</pre> 1218<p> 1219 That's it! To access the value, use the set and get accessor methods: 1220</p> 1221 1222<pre> 1223user.firstName.set("Google"); 1224int age = user.age.get(); 1225</pre> 1226<h3 id="observable_collections"> 1227 Observable Collections 1228</h3> 1229 1230<p> 1231 Some applications use more dynamic structures to hold data. Observable 1232 collections allow keyed access to these data objects. 1233 {@link android.databinding.ObservableArrayMap} is 1234 useful when the key is a reference type, such as String. 1235</p> 1236 1237<pre> 1238ObservableArrayMap<String, Object> user = new ObservableArrayMap<>(); 1239user.put("firstName", "Google"); 1240user.put("lastName", "Inc."); 1241user.put("age", 17); 1242</pre> 1243<p> 1244 In the layout, the map may be accessed through the String keys: 1245</p> 1246 1247<pre> 1248<data> 1249 <import type="android.databinding.ObservableMap"/> 1250 <variable name="user" type="ObservableMap&lt;String, Object>"/> 1251</data> 1252… 1253<TextView 1254 android:text='@{user["lastName"]}' 1255 android:layout_width="wrap_content" 1256 android:layout_height="wrap_content"/> 1257<TextView 1258 android:text='@{String.valueOf(1 + (Integer)user["age"])}' 1259 android:layout_width="wrap_content" 1260 android:layout_height="wrap_content"/> 1261</pre> 1262<p> 1263 {@link android.databinding.ObservableArrayList} is useful when the key is an integer: 1264</p> 1265 1266<pre> 1267ObservableArrayList<Object> user = new ObservableArrayList<>(); 1268user.add("Google"); 1269user.add("Inc."); 1270user.add(17); 1271</pre> 1272<p> 1273 In the layout, the list may be accessed through the indices: 1274</p> 1275 1276<pre> 1277<data> 1278 <import type="android.databinding.ObservableList"/> 1279 <import type="com.example.my.app.Fields"/> 1280 <variable name="user" type="ObservableList&lt;Object>"/> 1281</data> 1282… 1283<TextView 1284 android:text='@{user[Fields.LAST_NAME]}' 1285 android:layout_width="wrap_content" 1286 android:layout_height="wrap_content"/> 1287<TextView 1288 android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}' 1289 android:layout_width="wrap_content" 1290 android:layout_height="wrap_content"/> 1291</pre> 1292<h2 id="generated_binding"> 1293 Generated Binding 1294</h2> 1295 1296<p> 1297 The generated binding class links the layout variables with the Views within 1298 the layout. As discussed earlier, the name and package of the Binding may be 1299 <a href="#custom_binding_class_names">customized</a>. The Generated binding 1300 classes all extend {@link android.databinding.ViewDataBinding}. 1301</p> 1302 1303<h3 id="creating"> 1304 Creating 1305</h3> 1306 1307<p> 1308 The binding should be created soon after inflation to ensure that the View 1309 hierarchy is not disturbed prior to binding to the Views with expressions 1310 within the layout. There are a few ways to bind to a layout. The most common 1311 is to use the static methods on the Binding class.The inflate method inflates 1312 the View hierarchy and binds to it all it one step. There is a simpler 1313 version that only takes a {@link android.view.LayoutInflater} and one that takes a 1314 {@link android.view.ViewGroup} as well: 1315</p> 1316 1317<pre> 1318MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater); 1319MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false); 1320</pre> 1321<p> 1322 If the layout was inflated using a different mechanism, it may be bound 1323 separately: 1324</p> 1325 1326<pre> 1327MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot); 1328</pre> 1329<p> 1330 Sometimes the binding cannot be known in advance. In such cases, the binding 1331 can be created using the {@link android.databinding.DataBindingUtil} class: 1332</p> 1333 1334<pre> 1335ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId, 1336 parent, attachToParent); 1337ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId); 1338</pre> 1339<h3 id="views_with_ids"> 1340 Views With IDs 1341</h3> 1342 1343<p> 1344 A public final field will be generated for each View with an ID in the 1345 layout. The binding does a single pass on the View hierarchy, extracting the 1346 Views with IDs. This mechanism can be faster than calling findViewById for 1347 several Views. For example: 1348</p> 1349 1350<pre> 1351<layout xmlns:android="http://schemas.android.com/apk/res/android"> 1352 <data> 1353 <variable name="user" type="com.example.User"/> 1354 </data> 1355 <LinearLayout 1356 android:orientation="vertical" 1357 android:layout_width="match_parent" 1358 android:layout_height="match_parent"> 1359 <TextView android:layout_width="wrap_content" 1360 android:layout_height="wrap_content" 1361 android:text="@{user.firstName}" 1362 android:id="@+id/firstName"/> 1363 <TextView android:layout_width="wrap_content" 1364 android:layout_height="wrap_content" 1365 android:text="@{user.lastName}" 1366 android:id="@+id/lastName"/> 1367 </LinearLayout> 1368</layout> 1369</pre> 1370<p> 1371 Will generate a binding class with: 1372</p> 1373 1374<pre> 1375public final TextView firstName; 1376public final TextView lastName; 1377</pre> 1378<p> 1379 IDs are not nearly as necessary as without data binding, but there are still 1380 some instances where access to Views are still necessary from code. 1381</p> 1382 1383<h3 id="variables2"> 1384 Variables 1385</h3> 1386 1387<p> 1388 Each variable will be given accessor methods. 1389</p> 1390 1391<pre> 1392<data> 1393 <import type="android.graphics.drawable.Drawable"/> 1394 <variable name="user" type="com.example.User"/> 1395 <variable name="image" type="Drawable"/> 1396 <variable name="note" type="String"/> 1397</data> 1398</pre> 1399<p> 1400 will generate setters and getters in the binding: 1401</p> 1402 1403<pre> 1404public abstract com.example.User getUser(); 1405public abstract void setUser(com.example.User user); 1406public abstract Drawable getImage(); 1407public abstract void setImage(Drawable image); 1408public abstract String getNote(); 1409public abstract void setNote(String note); 1410</pre> 1411<h3 id="viewstubs"> 1412 ViewStubs 1413</h3> 1414 1415<p> 1416 {@link android.view.ViewStub}s are a little different from normal Views. They start off invisible 1417 and when they either are made visible or are explicitly told to inflate, they 1418 replace themselves in the layout by inflating another layout. 1419</p> 1420 1421<p> 1422 Because the <code>ViewStub</code> essentially disappears from the View hierarchy, the View 1423 in the binding object must also disappear to allow collection. Because the 1424 Views are final, a {@link android.databinding.ViewStubProxy} object takes the place of the 1425 <code>ViewStub</code>, giving the developer access to the ViewStub when it exists and also 1426 access to the inflated View hierarchy when the <code>ViewStub</code> has been inflated. 1427</p> 1428 1429<p> 1430 When inflating another layout, a binding must be established for the new 1431 layout. Therefore, the <code>ViewStubProxy</code> must listen to the <code>ViewStub</code>'s 1432 {@link android.view.ViewStub.OnInflateListener} and establish the binding at that time. Since 1433 only one can exist, the <code>ViewStubProxy</code> allows the developer to set an 1434 <code>OnInflateListener</code> on it that it will call after establishing the binding. 1435</p> 1436 1437<h3 id="advanced_binding"> 1438 Advanced Binding 1439</h3> 1440 1441<h4 id="dynamic_variables"> 1442 Dynamic Variables 1443</h4> 1444 1445<p> 1446 At times, the specific binding class won't be known. For example, a 1447 {@link android.support.v7.widget.RecyclerView.Adapter} operating against arbitrary layouts 1448 won't know the specific binding class. It still must assign the binding value during the 1449 {@link android.support.v7.widget.RecyclerView.Adapter#onBindViewHolder}. 1450</p> 1451 1452<p> 1453 In this example, all layouts that the RecyclerView binds to have an "item" 1454 variable. The <code>BindingHolder</code> has a <code>getBinding</code> method returning the 1455 {@link android.databinding.ViewDataBinding} base. 1456</p> 1457 1458<pre> 1459public void onBindViewHolder(BindingHolder holder, int position) { 1460 final T item = mItems.get(position); 1461 holder.getBinding().setVariable(BR.item, item); 1462 holder.getBinding().executePendingBindings(); 1463} 1464</pre> 1465<h4 id="immediate_binding"> 1466 Immediate Binding 1467</h4> 1468 1469<p> 1470 When a variable or observable changes, the binding will be scheduled to 1471 change before the next frame. There are times, however, when binding must be 1472 executed immediately. To force execution, use the 1473 {@link android.databinding.ViewDataBinding#executePendingBindings()} method. 1474</p> 1475 1476<h4> 1477 Background Thread 1478</h4> 1479 1480<p> 1481 You can change your data model in a background thread as long as it is not a 1482 collection. Data binding will localize each variable / field while evaluating 1483 to avoid any concurrency issues. 1484</p> 1485 1486<h2 id="attribute_setters"> 1487 Attribute Setters 1488</h2> 1489 1490<p> 1491 Whenever a bound value changes, the generated binding class must call a 1492 setter method on the View with the binding expression. The data binding 1493 framework has ways to customize which method to call to set the value. 1494</p> 1495 1496<h3 id="automatic_setters"> 1497 Automatic Setters 1498</h3> 1499For an attribute, data binding tries to find the method setAttribute. The 1500namespace for the attribute does not matter, only the attribute name itself. 1501<p> 1502 For example, an expression associated with TextView's attribute 1503 <strong><code>android:text</code></strong> will look for a setText(String). 1504 If the expression returns an int, data binding will search for a setText(int) 1505 method. Be careful to have the expression return the correct type, casting if 1506 necessary. Note that data binding will work even if no attribute exists with 1507 the given name. You can then easily "create" attributes for any setter by 1508 using data binding. For example, support DrawerLayout doesn't have any 1509 attributes, but plenty of setters. You can use the automatic setters to use 1510 one of these. 1511</p> 1512 1513<pre> 1514<android.support.v4.widget.<strong>DrawerLayout 1515 android:layout_width="wrap_content" 1516 android:layout_height="wrap_content" 1517 app:scrimColor="@{@color/scrim}" 1518 app:drawerListener="@{fragment.drawerListener}"/></strong> 1519</pre> 1520<h3 id="renamed_setters"> 1521 Renamed Setters 1522</h3> 1523 1524<p> 1525 Some attributes have setters that don't match by name. For these 1526 methods, an attribute may be associated with the setter through 1527 {@link android.databinding.BindingMethods} annotation. This must be associated with 1528 a class and contains {@link android.databinding.BindingMethod} annotations, one for 1529 each renamed method. For example, the <strong><code>android:tint</code></strong> attribute 1530 is really associated with {@link android.widget.ImageView#setImageTintList}, not 1531 <code>setTint</code>. 1532</p> 1533 1534<pre> 1535@BindingMethods({ 1536 @BindingMethod(type = "android.widget.ImageView", 1537 attribute = "android:tint", 1538 method = "setImageTintList"), 1539}) 1540</pre> 1541<p> 1542 It is unlikely that developers will need to rename setters; the android 1543 framework attributes have already been implemented. 1544</p> 1545 1546<h3 id="custom_setters"> 1547 Custom Setters 1548</h3> 1549 1550<p> 1551 Some attributes need custom binding logic. For example, there is no 1552 associated setter for the <strong><code>android:paddingLeft</code></strong> 1553 attribute. Instead, <code>setPadding(left, top, right, bottom)</code> exists. 1554 A static binding adapter method with the {@link android.databinding.BindingAdapter} 1555 annotation allows the developer to customize how a setter for an attribute is 1556 called. 1557</p> 1558 1559<p> 1560 The android attributes have already had <code>BindingAdapter</code>s created. 1561 For example, here is the one for <code>paddingLeft</code>: 1562</p> 1563 1564<pre> 1565@BindingAdapter("android:paddingLeft") 1566public static void setPaddingLeft(View view, int padding) { 1567 view.setPadding(padding, 1568 view.getPaddingTop(), 1569 view.getPaddingRight(), 1570 view.getPaddingBottom()); 1571} 1572</pre> 1573<p> 1574 Binding adapters are useful for other types of customization. For example, a 1575 custom loader can be called off-thread to load an image. 1576</p> 1577 1578<p> 1579 Developer-created binding adapters will override the data binding default 1580 adapters when there is a conflict. 1581</p> 1582 1583<p> 1584 You can also have adapters that receive multiple parameters. 1585</p> 1586 1587<pre> 1588@BindingAdapter({"bind:imageUrl", "bind:error"}) 1589public static void loadImage(ImageView view, String url, Drawable error) { 1590 Picasso.with(view.getContext()).load(url).error(error).into(view); 1591} 1592</pre> 1593<pre> 1594<ImageView app:imageUrl=“@{venue.imageUrl}” 1595app:error=“@{@drawable/venueError}”/> 1596</pre> 1597 1598<p> 1599 This adapter will be called if both <strong>imageUrl</strong> and 1600 <strong>error</strong> are used for an ImageView and <em>imageUrl</em> is a 1601 string and <em>error</em> is a drawable. 1602</p> 1603 1604<ul> 1605 <li>Custom namespaces are ignored during matching. 1606 </li> 1607 1608 <li>You can also write adapters for android namespace. 1609 </li> 1610</ul> 1611 1612<p> 1613 Binding adapter methods may optionally take the old values in their handlers. A method 1614 taking old and new values should have all old values for the attributes come first, followed 1615 by the new values: 1616</p> 1617<pre> 1618@BindingAdapter("android:paddingLeft") 1619public static void setPaddingLeft(View view, int oldPadding, int newPadding) { 1620 if (oldPadding != newPadding) { 1621 view.setPadding(newPadding, 1622 view.getPaddingTop(), 1623 view.getPaddingRight(), 1624 view.getPaddingBottom()); 1625 } 1626} 1627</pre> 1628<p> 1629 Event handlers may only be used with interfaces or abstract classes with one abstract method. 1630 For example: 1631</p> 1632<pre> 1633@BindingAdapter("android:onLayoutChange") 1634public static void setOnLayoutChangeListener(View view, View.OnLayoutChangeListener oldValue, 1635 View.OnLayoutChangeListener newValue) { 1636 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 1637 if (oldValue != null) { 1638 view.removeOnLayoutChangeListener(oldValue); 1639 } 1640 if (newValue != null) { 1641 view.addOnLayoutChangeListener(newValue); 1642 } 1643 } 1644} 1645</pre> 1646<p> 1647 When a listener has multiple methods, it must be split into multiple listeners. For example, 1648 {@link android.view.View.OnAttachStateChangeListener} has two methods: 1649 {@link android.view.View.OnAttachStateChangeListener#onViewAttachedToWindow onViewAttachedToWindow()} and 1650 {@link android.view.View.OnAttachStateChangeListener#onViewDetachedFromWindow onViewDetachedFromWindow()}. 1651 We must then create two interfaces to differentiate the attributes and handlers for them. 1652</p> 1653 1654<pre> 1655@TargetApi(VERSION_CODES.HONEYCOMB_MR1) 1656public interface OnViewDetachedFromWindow { 1657 void onViewDetachedFromWindow(View v); 1658} 1659 1660@TargetApi(VERSION_CODES.HONEYCOMB_MR1) 1661public interface OnViewAttachedToWindow { 1662 void onViewAttachedToWindow(View v); 1663} 1664</pre> 1665<p> 1666 Because changing one listener will also affect the other, we must have three different 1667 binding adapters, one for each attribute and one for both, should they both be set. 1668</p> 1669<pre> 1670@BindingAdapter("android:onViewAttachedToWindow") 1671public static void setListener(View view, OnViewAttachedToWindow attached) { 1672 setListener(view, null, attached); 1673} 1674 1675@BindingAdapter("android:onViewDetachedFromWindow") 1676public static void setListener(View view, OnViewDetachedFromWindow detached) { 1677 setListener(view, detached, null); 1678} 1679 1680@BindingAdapter({"android:onViewDetachedFromWindow", "android:onViewAttachedToWindow"}) 1681public static void setListener(View view, final OnViewDetachedFromWindow detach, 1682 final OnViewAttachedToWindow attach) { 1683 if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) { 1684 final OnAttachStateChangeListener newListener; 1685 if (detach == null && attach == null) { 1686 newListener = null; 1687 } else { 1688 newListener = new OnAttachStateChangeListener() { 1689 @Override 1690 public void onViewAttachedToWindow(View v) { 1691 if (attach != null) { 1692 attach.onViewAttachedToWindow(v); 1693 } 1694 } 1695 1696 @Override 1697 public void onViewDetachedFromWindow(View v) { 1698 if (detach != null) { 1699 detach.onViewDetachedFromWindow(v); 1700 } 1701 } 1702 }; 1703 } 1704 final OnAttachStateChangeListener oldListener = ListenerUtil.trackListener(view, 1705 newListener, R.id.onAttachStateChangeListener); 1706 if (oldListener != null) { 1707 view.removeOnAttachStateChangeListener(oldListener); 1708 } 1709 if (newListener != null) { 1710 view.addOnAttachStateChangeListener(newListener); 1711 } 1712 } 1713} 1714</pre> 1715<p> 1716 The above example is slightly more complicated than normal because View uses add and remove 1717 for the listener instead of a set method for {@link android.view.View.OnAttachStateChangeListener}. 1718 The <code>android.databinding.adapters.ListenerUtil</code> class helps keep track of the previous 1719 listeners so that they may be removed in the Binding Adaper. 1720</p> 1721<p> 1722 By annotating the interfaces <code>OnViewDetachedFromWindow</code> and 1723 <code>OnViewAttachedToWindow</code> with 1724 <code>@TargetApi(VERSION_CODES.HONEYCOMB_MR1)</code>, the data binding code 1725 generator knows that the listener should only be generated when running on Honeycomb MR1 1726 and new devices, the same version supported by 1727 {@link android.view.View#addOnAttachStateChangeListener}. 1728</p> 1729<h2 id="converters"> 1730 Converters 1731</h2> 1732 1733<h3 id="object_conversions"> 1734 Object Conversions 1735</h3> 1736 1737<p> 1738 When an Object is returned from a binding expression, a setter will be chosen 1739 from the automatic, renamed, and custom setters. The Object will be cast to a 1740 parameter type of the chosen setter. 1741</p> 1742 1743<p> 1744 This is a convenience for those using ObservableMaps to hold data. for 1745 example: 1746</p> 1747 1748<pre> 1749<TextView 1750 android:text='@{userMap["lastName"]}' 1751 android:layout_width="wrap_content" 1752 android:layout_height="wrap_content"/> 1753</pre> 1754 1755<p> 1756The <code>userMap</code> returns an Object and that Object will be automatically cast to 1757 parameter type found in the setter <code>setText(CharSequence)</code>. When there 1758 may be confusion about the parameter type, the developer will need 1759 to cast in the expression. 1760</p> 1761 1762<h3 id="custom_conversions">Custom Conversions</h3> 1763 1764<p> 1765 Sometimes conversions should be automatic between specific types. For 1766 example, when setting the background: 1767</p> 1768 1769<pre> 1770<View 1771 android:background="@{isError ? @color/red : @color/white}" 1772 android:layout_width="wrap_content" 1773 android:layout_height="wrap_content"/> 1774</pre> 1775<p> 1776 Here, the background takes a <code>Drawable</code>, but the color is an 1777 integer. Whenever a <code>Drawable</code> is expected and an integer is 1778 returned, the <code>int</code> should be converted to a 1779 <code>ColorDrawable</code>. This conversion is done using a static method 1780 with a BindingConversion annotation: 1781</p> 1782 1783<pre> 1784@BindingConversion 1785public static ColorDrawable convertColorToDrawable(int color) { 1786 return new ColorDrawable(color); 1787} 1788</pre> 1789<p> 1790 Note that conversions only happen at the setter level, so it is <strong>not 1791 allowed</strong> to mix types like this: 1792</p> 1793 1794<pre> 1795<View 1796 android:background="@{isError ? @drawable/error : @color/white}" 1797 android:layout_width="wrap_content" 1798 android:layout_height="wrap_content"/> 1799</pre> 1800 1801<h3 id="studio_support">Android Studio Support for Data Binding</h3> 1802 1803<p> 1804Android Studio supports many of the code editing features for data binding code. 1805For example, it supports the following features for data binding expressions:</p> 1806<ul> 1807<li>Syntax highlighting</li> 1808<li>Flagging of expression language syntax errors</li> 1809<li>XML code completion</li> 1810<li>References, including <a class="external-link" 1811href="https://www.jetbrains.com/help/idea/2016.1/navigation-in-source-code.html?origin=old_help"> 1812navigation</a> (such as navigate to a declaration) and 1813<a class="external-link" 1814href="https://www.jetbrains.com/help/idea/2016.1/viewing-inline-documentation.html?origin=old_help"> 1815quick documentation</a></li> 1816</ul> 1817 1818<p class="note"><strong>Note:</strong> Arrays and a 1819<a href="https://docs.oracle.com/javase/tutorial/java/generics/types.html" 1820class="external-link">generic type</a>, such as the {@link 1821android.databinding.Observable} class, might display 1822errors when there are no errors.</p> 1823 1824<p> 1825The Preview pane displays default values for data binding expressions if 1826provided. In the following 1827example excerpt of an element from a layout XML file, the Preview pane displays 1828the {@code PLACEHOLDER} default text value in the <code>TextView</code>. 1829</p> 1830 1831<pre> 1832<TextView android:layout_width="wrap_content" 1833 android:layout_height="wrap_content" 1834 android:text="@{user.firstName, default=PLACEHOLDER}"/> 1835</pre> 1836 1837<p> 1838If you need to display a default value during the design phase of your project, 1839you can also use tools attributes instead of default expression values, as 1840described in 1841<a class="external-link" 1842href="http://tools.android.com/tips/layout-designtime-attributes"> 1843Designtime Layout Attributes</a>. 1844</p> 1845 1846