Data Binding Library

導(dǎo)航:

本文檔解釋了如何使用數(shù)據(jù)綁定庫(kù)來(lái)編寫(xiě)聲明式布局喷面,并盡量減少綁定應(yīng)用程序邏輯和布局所需的膠合代碼。

數(shù)據(jù)綁定庫(kù)提供了靈活性和廣泛的兼容性 - 這是一個(gè)支持庫(kù)腹备,所以你可以在Android 2.1(API級(jí)別7+)的所有Android平臺(tái)上使用它溃肪。

要使用數(shù)據(jù)綁定救湖,Android Plugin for Gradle 1.5.0-alpha1 或更高版本是必需的。了解如何更新Android Plugin for Gradle艾疟。

1.配置環(huán)境

要開(kāi)始使用數(shù)據(jù)綁定押框,請(qǐng)從Android SDK管理器的支持庫(kù)中下載庫(kù)。

要配置應(yīng)用程序以使用數(shù)據(jù)綁定尿背,請(qǐng)將dataBinding 元素添加到應(yīng)用程序模塊中的build.gradle文件中端仰。

使用下面的代碼片段來(lái)配置數(shù)據(jù)綁定:

android {
    ....
    dataBinding {
        enabled = true
    }
}

如果您的應(yīng)用程序模塊依賴于使用數(shù)據(jù)綁定的庫(kù),則您的應(yīng)用程序模塊也必須在其build.gradle 配置數(shù)據(jù)綁定残家。

另外榆俺,請(qǐng)確保您使用的是Android Studio的兼容版本售躁。Android Studio 1.3及更高版本支持?jǐn)?shù)據(jù)綁定坞淮,如Android Studio支持?jǐn)?shù)據(jù)綁定中所述

2.數(shù)據(jù)綁定編譯器V2

Android Gradle插件3.1.0 Canary 6附帶一個(gè)可選的新編譯器陪捷。要開(kāi)始使用它回窘,請(qǐng)更新您的gradle.properties文件以包含以下行:

android.databinding.enableV2=true

在編譯器v2中:

  • ViewBinding類是在java編譯器之前由Android Gradle Plugin生成的。這可以避免由于不相關(guān)的原因?qū)е耲ava編譯失敗而導(dǎo)致太多的錯(cuò)誤肯定錯(cuò)誤市袖。
  • 在V1中啡直,編譯應(yīng)用程序時(shí)會(huì)重新生成庫(kù)的綁定類(以共享生成的代碼并訪問(wèn)最終的“BR”和“R”文件)烁涌。在V2中,庫(kù)保持其生成的綁定類以及映射器信息酒觅,這為多模塊項(xiàng)目顯著提高了數(shù)據(jù)綁定性能撮执。

請(qǐng)注意,這個(gè)新的編譯器是向后不兼容的舷丹,所以用v1編譯的庫(kù)不能被v2使用抒钱,反之亦然。

V2還會(huì)刪除一些很少使用的功能來(lái)允許這些更改:

  • 在V1中颜凯,一個(gè)應(yīng)用程序能夠提供綁定適配器谋币,可以覆蓋依賴項(xiàng)中的適配器。在V2中症概,它只對(duì)自己的模塊/應(yīng)用程序及其依賴項(xiàng)中的代碼生效蕾额。
  • 以前,如果一個(gè)布局文件在兩個(gè)或多個(gè)不同的資源配置中包含一個(gè) View具有相同id但不同類的數(shù)據(jù)彼城,則數(shù)據(jù)綁定將查找最常見(jiàn)的父類诅蝶。View當(dāng)配置之間的類型不匹配時(shí),它將始終默認(rèn)為精肃。
  • 在V2中秤涩,不同的模塊不能在清單中使用相同的包名稱,因?yàn)閿?shù)據(jù)綁定將使用該包名來(lái)生成綁定映射器類司抱。
3.數(shù)據(jù)綁定布局文件

3.1編寫(xiě)你的第一套數(shù)據(jù)綁定表達(dá)式

數(shù)據(jù)綁定布局文件稍有不同筐眷,layout作為根標(biāo)簽,后跟data 元素和 view根元素习柠。示例文件如下所示:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.firstName}"/>
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.lastName}"/>
   </LinearLayout>
</layout>

data標(biāo)簽中的user變量,描述了可以在布局中使用的屬性匀谣。

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

布局中的使用@{}語(yǔ)法表達(dá)式寫(xiě)入屬性。在這里资溃,TextView的文本被設(shè)置為用戶的firstName屬性:

<TextView android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@{user.firstName}"/>
Data Object
3.2 數(shù)據(jù)對(duì)象

現(xiàn)在讓我們假設(shè)你有一個(gè)普通的Java對(duì)象(PO??JO)用戶:

public class User {
   public final String firstName;
   public final String lastName;
   public User(String firstName, String lastName) {
       this.firstName = firstName;
       this.lastName = lastName;
   }
}

這種類型的對(duì)象的數(shù)據(jù)永遠(yuǎn)不會(huì)改變武翎。在應(yīng)用程序中通常會(huì)讀取一次數(shù)據(jù),之后再也不會(huì)更改溶锭。也可以使用JavaBeans對(duì)象:

public class User {
   private final String firstName;
   private final String lastName;
   public User(String firstName, String lastName) {
       this.firstName = firstName;
       this.lastName = lastName;
   }
   public String getFirstName() {
       return this.firstName;
   }
   public String getLastName() {
       return this.lastName;
   }
}

從數(shù)據(jù)綁定的角度來(lái)看宝恶,這兩個(gè)類是等價(jià)的。@{user.firstName}用于TextView android:text屬性的表達(dá)式將訪問(wèn)前一類中的firstName字段和后一類中的getFirstName()方法趴捅〉姹校或者,如果firstName()方法存在拱绑,也將被解析综芥。

3.3 綁定數(shù)據(jù)

默認(rèn)情況下,將根據(jù)布局文件的名稱生成一個(gè)Binding類猎拨,將其轉(zhuǎn)換為Pascal格式并將Binding后綴添加到該文件中膀藐。上面的布局文件是main_activity.xml這樣的生成類是MainActivityBinding屠阻。這個(gè)類將布局屬性(例如user變量)的所有綁定保存到布局的視圖中,并知道如何為綁定表達(dá)式賦值额各。創(chuàng)建綁定的最簡(jiǎn)單方法是在inflating時(shí)進(jìn)行:

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
   User user = new User("Test", "User");
   binding.setUser(user);
}

你完成了国觉!運(yùn)行應(yīng)用程序,你會(huì)看到用戶界面中的測(cè)試user虾啦◎燃樱或者,您可以通過(guò)以下方式獲取視圖:

MainActivityBinding binding = 
MainActivityBinding.inflate(getLayoutInflater());

如果您在ListView或RecyclerView適配器內(nèi)使用數(shù)據(jù)綁定項(xiàng)目缸逃,則可能更愿意使用:

ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
//or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
Event Handling
3.4 事件處理

數(shù)據(jù)綁定允許您編寫(xiě)表達(dá)式來(lái)處理從視圖中分派的事件(例如onClick)针饥。除少數(shù)例外,事件屬性名稱由偵聽(tīng)器方法的名稱來(lái)管理需频。View.OnLongClickListener 有一個(gè)方法 onLongClick()丁眼,所以這個(gè)事件的屬性是android:onLongClick。處理事件有兩種方法昭殉。

  • 方法引用:在你的表達(dá)式中苞七,你可以引用符合偵聽(tīng)器方法簽名的方法。當(dāng)表達(dá)式評(píng)估為方法引用時(shí)挪丢,數(shù)據(jù)綁定將方法引用和所有者對(duì)象包裝在偵聽(tīng)器中蹂风,并將該偵聽(tīng)器設(shè)置在目標(biāo)視圖上。如果表達(dá)式求值為null乾蓬,則數(shù)據(jù)綁定不會(huì)創(chuàng)建偵聽(tīng)器惠啄,而是設(shè)置空偵聽(tīng)器。
  • 監(jiān)聽(tīng)器綁定:這些是在事件發(fā)生時(shí)被評(píng)估的lambda表達(dá)式任内。數(shù)據(jù)綁定總是創(chuàng)建一個(gè)監(jiān)聽(tīng)器撵渡,它在視圖上設(shè)置。事件發(fā)送時(shí)死嗦,監(jiān)聽(tīng)器評(píng)估lambda表達(dá)式趋距。
3.4.1方法引用

事件可以直接綁定到處理方法,類似于 android:onClick可以分配給Activity中的方法越除。與View#onClick屬性相比节腐,一個(gè)主要的優(yōu)點(diǎn)是表達(dá)式在編譯時(shí)被處理,所以如果方法不存在或者它的簽名不正確摘盆,你會(huì)收到一個(gè)編譯時(shí)錯(cuò)誤翼雀。

方法引用和監(jiān)聽(tīng)器綁定的主要區(qū)別在于實(shí)際的監(jiān)聽(tīng)器實(shí)現(xiàn)是在綁定數(shù)據(jù)時(shí)創(chuàng)建的,而不是在事件觸發(fā)時(shí)創(chuàng)建的骡澈。如果您喜歡在事件發(fā)生時(shí)評(píng)估表達(dá)式锅纺,則應(yīng)該使用監(jiān)聽(tīng)器綁定掷空。

要將事件分配給其處理程序肋殴,請(qǐng)使用常規(guī)綁定表達(dá)式囤锉,其值是要調(diào)用的方法名稱。例如护锤,如果你的數(shù)據(jù)對(duì)象有兩個(gè)方法:

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

綁定表達(dá)式可以為View分配一個(gè)點(diǎn)擊監(jiān)聽(tīng)器:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="handlers" type="com.example.MyHandlers"/>
       <variable name="user" type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.firstName}"
           android:onClick="@{handlers::onClickFriend}"/>
   </LinearLayout>
</layout>

請(qǐng)注意官地,表達(dá)式中方法的簽名必須與Listener對(duì)象中方法的簽名完全匹配

3.4.2監(jiān)聽(tīng)器綁定

監(jiān)聽(tīng)器綁定是事件發(fā)生時(shí)運(yùn)行的綁定表達(dá)式。它們類似于方法引用烙懦,但是它們?cè)试S您運(yùn)行任意的數(shù)據(jù)綁定表達(dá)式驱入。此功能適用于Gradle 2.0版及更高版本的Android Gradle插件。

在方法引用中氯析,方法的參數(shù)必須與事件偵聽(tīng)器的參數(shù)匹配亏较。在監(jiān)聽(tīng)器綁定中,只有你的返回值必須與監(jiān)聽(tīng)器的期望返回值相匹配(除非它預(yù)期為void)掩缓。例如雪情,您可以有一個(gè)具有以下方法的演示者類:

public class Presenter {
    public void onSaveClick(Task task){}
}

然后你可以如下綁定點(diǎn)擊事件:

<?xml version="1.0" encoding="utf-8"?>
  <layout xmlns:android="http://schemas.android.com/apk/res/android">
      <data>
          <variable name="task" type="com.android.example.Task" />
          <variable name="presenter" type="com.android.example.Presenter" />
      </data>
      <LinearLayout
          android:layout_width="match_parent" 
          android:layout_height="match_parent">
          <Button
           android:layout_width="wrap_content" 
           android:layout_height="wrap_content"
           android:onClick="@{() -> presenter.onSaveClick(task)}" />
      </LinearLayout>
  </layout>

監(jiān)聽(tīng)器僅允許只允許由lambda表達(dá)式作為根元素的表達(dá)式。在表達(dá)式中使用回調(diào)函數(shù)時(shí)你辣,數(shù)據(jù)綁定會(huì)自動(dòng)為事件創(chuàng)建必要的偵聽(tīng)器和注冊(cè)表巡通。當(dāng)視圖觸發(fā)事件時(shí),數(shù)據(jù)綁定將評(píng)估給定的表達(dá)式舍哄。就像在常規(guī)的綁定表達(dá)式中一樣宴凉,當(dāng)這些監(jiān)聽(tīng)器表達(dá)式被評(píng)估的時(shí)候,你仍然可以獲得數(shù)據(jù)綁定的null和線程安全性表悬。

請(qǐng)注意弥锄,在上面的例子中,我們沒(méi)有定義view傳入?yún)?shù)onClick(android.view.View)蟆沫。監(jiān)聽(tīng)器綁定為監(jiān)聽(tīng)器參數(shù)提供了兩個(gè)選擇:您可以忽略該方法的所有參數(shù)或?qū)⑵淙棵婕ァH绻胍麉?shù),則可以在表達(dá)式中使用它們饥追。例如图仓,上面的表達(dá)式可以寫(xiě)成:

  android:onClick="@{(view) -> presenter.onSaveClick(task)}"

或者如果你想使用表達(dá)式中的參數(shù),它可以如下工作:

public class Presenter {
    public void onSaveClick(View view, Task task){}
}

---

android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"


您可以使用多于一個(gè)參數(shù)的lambda表達(dá)式:

public class Presenter {
    public void onCompletedChanged(Task task, boolean completed){}
}
------
 <CheckBox android:layout_width="wrap_content" 
                   android:layout_height="wrap_content"
                   android:onCheckedChanged="@{(cb, isChecked) -> 
                   presenter.completeChanged(task, isChecked)}" />

如果正在偵聽(tīng)的事件返回一個(gè)其類型不是void的值但绕,則表達(dá)式必須返回相同類型的值救崔。例如,如果要監(jiān)聽(tīng)長(zhǎng)按事件捏顺,則應(yīng)該返回表達(dá)式boolean六孵。

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

如果由于是null對(duì)象而無(wú)法評(píng)估表達(dá)式,Data Binding將返回該類型的默認(rèn)Java值幅骄。例如劫窒,null返回引用類型,0返回 int拆座, false返回 boolean等主巍。

如果您需要使用謂詞(例如三元)表達(dá)式冠息,則可以將 void用作符號(hào)。

android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}"
避免復(fù)雜的監(jiān)聽(tīng)

監(jiān)聽(tīng)器表達(dá)式非常強(qiáng)大孕索,可以讓你的代碼非常容易閱讀逛艰。另一方面,包含復(fù)雜表達(dá)式的監(jiān)聽(tīng)會(huì)使您的布局難以閱讀和維護(hù)搞旭。這些表達(dá)式應(yīng)該像從UI中傳遞可用數(shù)據(jù)到回調(diào)方法一樣簡(jiǎn)單散怖。您應(yīng)該在您從偵聽(tīng)器表達(dá)式調(diào)用的回調(diào)方法內(nèi)實(shí)現(xiàn)任何業(yè)務(wù)邏輯。

存在一些專門的單擊事件處理程序肄渗,它們需要一個(gè)屬性镇眷, android:onClick以避免沖突。已經(jīng)創(chuàng)建了以下屬性以避免這種沖突:

class Listener Setter Attribute
SearchView setOnSearchClickListener(View.OnClickListener) android:onSearchClick
ZoomControls setOnZoomInClickListener(View.OnClickListener) android:onZoomIn
ZoomControls setOnZoomOutClickListener(View.OnClickListener) android:onZoomOut

4.布局細(xì)節(jié)


4.1 import

data元素中可以使用零個(gè)或多個(gè)import元素,這些就像在Java中一樣可以輕松地引用布局文件中的類翎嫡。

<data>
    <import type="android.view.View"/>
</data>

現(xiàn)在偏灿,可以在你的綁定表達(dá)式中使用視圖:

<TextView
   android:text="@{user.lastName}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>

當(dāng)有類名沖突時(shí),其中一個(gè)類可能會(huì)被重命名為“alias:”

<import type="android.view.View"/>
<import type="com.example.real.estate.View"
        alias="Vista"/>

現(xiàn)在钝的,Vista可能會(huì)以com.example.real.estate.View翁垂,View可能以android.view.View在布局文件內(nèi)引用。導(dǎo)入的類型可以用作變量和表達(dá)式中的類型引用:

<data>
    <import type="com.example.User"/>
    <import type="java.util.List"/>
    <variable name="user" type="User"/>
    <variable name="userList" type="List&lt;User&gt;"/>
</data>

注意:Android Studio尚未處理導(dǎo)入硝桩,因此導(dǎo)入變量的自動(dòng)填充可能無(wú)法在您的IDE中工作沿猜。您的應(yīng)用程序仍然可以正常編譯,您可以通過(guò)在變量定義中使用完全限定的名稱來(lái)解決IDE問(wèn)題碗脊。

<TextView
   android:text="@{((User)(user.connection)).lastName}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

當(dāng)在表達(dá)式中引用靜態(tài)字段和方法時(shí)啼肩,也可以使用導(dǎo)入的類型:

<data>
    <import type="com.example.MyStringUtils"/>
    <variable name="user" type="com.example.User"/>
</data>
…
<TextView
   android:text="@{MyStringUtils.capitalize(user.lastName)}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

就像在Java中一樣,java.lang.*自動(dòng)導(dǎo)入衙伶。

4.2 Variables

data元素內(nèi)可以使用任意數(shù)量的variable元素祈坠,每個(gè)variable元素描述可以在布局上設(shè)置的屬性,以用于布局文件中的綁定表達(dá)式矢劲。

<data>
    <import type="android.graphics.drawable.Drawable"/>
    <variable name="user"  type="com.example.User"/>
    <variable name="image" type="Drawable"/>
    <variable name="note"  type="String"/>
</data>

變量類型在編譯時(shí)被檢查赦拘,所以如果一個(gè)變量實(shí)現(xiàn)Observable或者是一個(gè)observable collection,那么這個(gè)類型應(yīng)該被反映出來(lái)芬沉。如果變量是不實(shí)現(xiàn)Observable接口的基類或接口躺同,將不會(huì)觀察變量!

當(dāng)不同的配置文件(例如橫向或縱向)有不同的布局文件時(shí)丸逸,變量將被合并蹋艺。這些布局文件之間不得存在沖突的變量定義。
生成的綁定類將為每個(gè)描述的變量設(shè)置一個(gè)setter和getter黄刚。變量將采用默認(rèn)的Java值捎谨,直到調(diào)用者被調(diào)用 - null是引用類型,0intfalseboolean等涛救。

根據(jù)需要生成一個(gè)名為context的特殊變量用于綁定表達(dá)式畏邢。context是視圖的getContext()得到的Contextcontext變量將被具有該名稱的顯式變量聲明覆蓋州叠。

4.3自定義綁定類名稱

默認(rèn)情況下,根據(jù)布局文件的名稱生成一個(gè)Binding類凶赁,以大寫(xiě)字母開(kāi)頭咧栗,刪除下劃線(_)并大寫(xiě)下面的字母,然后后綴“Binding”虱肄。這個(gè)類將被放置在模塊包下的數(shù)據(jù)綁定包中致板。例如,布局文件contact_item.xml將生成 ContactItemBinding咏窿。如果模塊包是 com.example.my.app斟或,那么它將被放入com.example.my.app.databinding

綁定類可以通過(guò)調(diào)整class元素的屬性來(lái)重命名或放置data在不同的包中集嵌。

<data class="ContactItem">
    ...
</data>

這將在模塊包中的數(shù)據(jù)綁定包中生成綁定類ContactItem萝挤。如果該類應(yīng)該在模塊包中的其他包中生成,則可以用.作為前綴:

<data class=".ContactItem">
    ...
</data>

在這種情況下根欧,ContactItem直接在模塊包中生成怜珍。如果提供完整的軟件包,則可以在任何軟件包中:

<data class="com.example.ContactItem">
    ...
</data>
4.4 Includes

通過(guò)使用應(yīng)用程序名稱空間和屬性的變量名凤粗,變量可以被傳遞到包含布局的包含綁定中:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:bind="http://schemas.android.com/apk/res-auto">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <include layout="@layout/name"
           bind:user="@{user}"/>
       <include layout="@layout/contact"
           bind:user="@{user}"/>
   </LinearLayout>
</layout>

在這里酥泛,name.xmlcontact.xml布局文件中都必須有一個(gè)user變量。

數(shù)據(jù)綁定不支持include作為merge元素的直接子元素嫌拣。例如柔袁,不支持以下布局:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:bind="http://schemas.android.com/apk/res-auto">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <merge>
       <include layout="@layout/name"
           bind:user="@{user}"/>
       <include layout="@layout/contact"
           bind:user="@{user}"/>
   </merge>
</layout>
4.5 1. 表達(dá)式語(yǔ)言
共同特征

表達(dá)式語(yǔ)言看起來(lái)很像Java表達(dá)式。這些是一樣的:

  • 數(shù)學(xué)的: + - / * %
  • 字符串連接: +
  • 邏輯: && ||
  • 二進(jìn)制: & | ^
  • 一元: + - ! ~
  • 轉(zhuǎn)移: >> >>> <<
  • 對(duì)照: == > < >= <=
  • instanceof
  • 分組: ()
  • 文字 - 字符异逐,字符串捶索,數(shù)字, null
  • Cast
  • 方法調(diào)用
  • 字段訪問(wèn)
  • 數(shù)組訪問(wèn) []
  • 三元操作符 ?:

例子:

android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}
不支持的操作

您可以在Java中使用的表達(dá)式語(yǔ)法中缺少一些操作灰瞻。

  • this
  • super
  • new
  • 明確的泛型調(diào)用
空合并運(yùn)算符

null合并運(yùn)算符(??)選擇左操作數(shù)(如果不是null)或右(如果為空)情组。

android:text="@{user.displayName ?? user.lastName}"

這在功能上等同于:

android:text="@{user.displayName != null ? user.displayName : user.lastName}"

屬性引用

第一個(gè)已經(jīng)在上面的編寫(xiě)第一個(gè)數(shù)據(jù)綁定表達(dá)式中討論過(guò)了:簡(jiǎn)短形式的JavaBean引用。當(dāng)一個(gè)表達(dá)式引用一個(gè)類的屬性時(shí)箩祥,它對(duì)字段院崇,獲取器和ObservableFields使用相同的格式。

android:text="@{user.lastName}"
避免空指針異常

生成的數(shù)據(jù)綁定代碼自動(dòng)檢查空值并避免空指針異常袍祖。例如底瓣,在 @{user.name}表達(dá)式中如果user為null, user.name將被賦予其默認(rèn)值(null)。如果你是引用user.age捐凭,年齡是一個(gè)int拨扶,那么它將默認(rèn)為0。

集合

公共集合:數(shù)組茁肠,列表患民,稀疏列表和地圖,為了方便可以使用[]操作符垦梆。

<data>
    <import type="android.util.SparseArray"/>
    <import type="java.util.Map"/>
    <import type="java.util.List"/>
    <variable name="list" type="List&lt;String&gt;"/>
    <variable name="sparse" type="SparseArray&lt;String&gt;"/>
    <variable name="map" type="Map&lt;String, String&gt;"/>
    <variable name="index" type="int"/>
    <variable name="key" type="String"/>
</data>
…
android:text="@{list[index]}"
…
android:text="@{sparse[index]}"
…
android:text="@{map[key]}"
字符串文字

在屬性值周圍使用單引號(hào)時(shí)匹颤,在表達(dá)式中使用雙引號(hào)很容易:

android:text='@{map["firstName"]}'

也可以使用雙引號(hào)來(lái)包圍屬性值。這樣做時(shí)托猩,字符串文字應(yīng)該使用'或者反引號(hào)( ` )印蓖。

android:text="@{map[`firstName`}"
android:text="@{map['firstName']}"
資源

使用正常語(yǔ)法可以將資源作為表達(dá)式的一部分進(jìn)行訪問(wèn):

android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"

格式字符串和復(fù)數(shù)可以通過(guò)提供參數(shù)來(lái)評(píng)估:

android:text="@{@string/nameFormat(firstName, lastName)}"
android:text="@{@plurals/banana(bananaCount)}"

當(dāng)一個(gè)復(fù)數(shù)有多個(gè)參數(shù)時(shí),所有參數(shù)都應(yīng)該傳遞:

  Have an orange
  Have %d oranges

android:text="@{@plurals/orange(orangeCount, orangeCount)}"

有些資源需要明確的類型評(píng)估京腥。

Type Normal Reference Expression Reference
String[] @array @stringArray
int[] @array @intArray
TypedArray @array @typedArray
Animator @animator @animator
StateListAnimator @animator @stateListAnimator
color int @color @color
ColorStateList @color @colorStateList
5.數(shù)據(jù)對(duì)象

任何普通的舊Java對(duì)象(PO??JO)都可以用于數(shù)據(jù)綁定赦肃,但修改POJO不會(huì)導(dǎo)致UI更新。數(shù)據(jù)綁定的真正威力可以通過(guò)給你的數(shù)據(jù)對(duì)象提供在數(shù)據(jù)改變時(shí)通知的能力公浪。有三種不同的數(shù)據(jù)更改通知機(jī)制: 可觀察對(duì)象他宛, 可觀察字段可觀察集合
當(dāng)這些可觀察的數(shù)據(jù)對(duì)象之一被綁定到UI并且數(shù)據(jù)對(duì)象的屬性改變時(shí)欠气,UI將被自動(dòng)更新堕汞。

5.1可觀察的對(duì)象

實(shí)現(xiàn)Observable接口的類將允許綁定將單個(gè)偵聽(tīng)器附加到綁定對(duì)象,以偵聽(tīng)該對(duì)象上所有屬性的更改晃琳。

Observable接口具有添加和刪除偵聽(tīng)器的機(jī)制讯检,但通知由開(kāi)發(fā)人員決定。為了簡(jiǎn)化開(kāi)發(fā)卫旱,創(chuàng)建了一個(gè)BaseObservable基類來(lái)實(shí)現(xiàn)監(jiān)聽(tīng)器注冊(cè)機(jī)制人灼。數(shù)據(jù)類實(shí)現(xiàn)者仍然負(fù)責(zé)通知屬性何時(shí)更改,通過(guò)分配一個(gè)Bindable注釋給getter并且在setter中使用通知來(lái)完成的顾翼。

private static class User extends BaseObservable {
   private String firstName;
   private String lastName;
   @Bindable
   public String getFirstName() {
       return this.firstName;
   }
   @Bindable
   public String getLastName() {
       return this.lastName;
   }
   public void setFirstName(String firstName) {
       this.firstName = firstName;
       notifyPropertyChanged(BR.firstName);
   }
   public void setLastName(String lastName) {
       this.lastName = lastName;
       notifyPropertyChanged(BR.lastName);
   }
}

生成編譯期間Bindable注解在BR類文件中生成一個(gè)條目投放。而B(niǎo)R類文件將在模塊包中生成。如果數(shù)據(jù)類的基類不能改變适贸,那么Observable將會(huì)被實(shí)現(xiàn)灸芳,通過(guò)使用PropertyChangeRegistry去存儲(chǔ)和有效地通知偵聽(tīng)器。

5.2 可觀察字段

Observable類大有內(nèi)涵拜姿,所以開(kāi)發(fā)者想要節(jié)省時(shí)間和添加有幾個(gè)屬性烙样,可以使用ObservableField和它的兄弟姐妹
ObservableBooleanObservableByte蕊肥,ObservableChar谒获,ObservableShortObservableIntObservableLong批狱,ObservableFloat裸准,ObservableDouble,和ObservableParcelable赔硫。

ObservableFields是具有單個(gè)字段的自包含可觀察對(duì)象炒俱。原始版本在訪問(wèn)操作期間避免裝箱和取消裝箱。要使用爪膊,請(qǐng)?jiān)跀?shù)據(jù)類中創(chuàng)建一個(gè)公共final字段:

private static class User {
   public final ObservableField<String> firstName =
       new ObservableField<>();
   public final ObservableField<String> lastName =
       new ObservableField<>();
   public final ObservableInt age = new ObservableInt();
}

就這么簡(jiǎn)單权悟!要訪問(wèn)該值,請(qǐng)使用set和get訪問(wèn)器方法:

user.firstName.set("Google");
int age = user.age.get();
5.3 可觀察的集合

一些應(yīng)用程序使用更多的動(dòng)態(tài)結(jié)構(gòu)來(lái)保存數(shù)據(jù),可觀察集合允許對(duì)這些數(shù)據(jù)對(duì)象進(jìn)行鍵控訪問(wèn)惊完。當(dāng)鍵是引用類型(如String)時(shí)ObservableArrayMap非常有用僵芹。

ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();
user.put("firstName", "Google");
user.put("lastName", "Inc.");
user.put("age", 17);

在布局中处硬,可以通過(guò)String鍵訪問(wèn)map

<data>
    <import type="android.databinding.ObservableMap"/>
    <variable name="user" type="ObservableMap&lt;String, Object&gt;"/>
</data>
…
<TextView
   android:text='@{user["lastName"]}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>
<TextView
   android:text='@{String.valueOf(1 + (Integer)user["age"])}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

當(dāng)鍵是一個(gè)整數(shù)時(shí)使用ObservableArrayList

ObservableArrayList<Object> user = new ObservableArrayList<>();
user.add("Google");
user.add("Inc.");
user.add(17);

在布局中小槐,可以通過(guò)索引來(lái)訪問(wèn)列表:

<data>
    <import type="android.databinding.ObservableList"/>
    <import type="com.example.my.app.Fields"/>
    <variable name="user" type="ObservableList&lt;Object&gt;"/>
</data>
…
<TextView
   android:text='@{user[Fields.LAST_NAME]}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>
<TextView
   android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>
6.生成的綁定

生成的綁定類將布局變量與布局中的視圖鏈接起來(lái)。如前所述荷辕,綁定的名稱和包可能是 自定義的凿跳。生成的綁定類全部擴(kuò)展ViewDataBinding

6.1創(chuàng)建

應(yīng)該在inflation之后立即創(chuàng)建綁定疮方,以確保在綁定到布局中帶有表達(dá)式的視圖之前控嗜,View層次結(jié)構(gòu)不受干擾。有幾種方法可以綁定到布局骡显。最常見(jiàn)的是在Binding類中使用靜態(tài)方法疆栏。inflate方法inflate了View層次結(jié)構(gòu),并將其一步綁定惫谤。有一個(gè)簡(jiǎn)單的版本壁顶,只需要一個(gè)LayoutInflaterViewGroup

MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater);
MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false);

如果布局使用不同的inflate機(jī)制,它可能會(huì)被分開(kāi)綁定:

MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);

有時(shí)綁定不能預(yù)先知道溜歪。在這種情況下若专,綁定可以使用DataBindingUtil類創(chuàng)建:

ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId,
    parent, attachToParent);
ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);
6.2帶有ID的視圖

每個(gè)帶有ID的視圖將在布局中生成一個(gè)對(duì)應(yīng)的公開(kāi)fianl字段。該綁定在View層次結(jié)構(gòu)上執(zhí)行單個(gè)傳遞蝴猪,提取帶有ID的視圖调衰。這個(gè)機(jī)制可以比調(diào)用多個(gè)視圖的findViewById更快。例如:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.firstName}"
           android:id="@+id/firstName"/>
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.lastName}"
          android:id="@+id/lastName"/>
   </LinearLayout>
</layout>

將會(huì)生成一個(gè)綁定類:

public final TextView firstName;
public final TextView lastName;

ID在數(shù)據(jù)綁定時(shí)不是必須的自阱,但是仍然有一些情況下代碼仍然需要訪問(wèn)視圖嚎莉。

6.3變量

每個(gè)變量將被賦予訪問(wèn)器方法。

<data>
    <import type="android.graphics.drawable.Drawable"/>
    <variable name="user"  type="com.example.User"/>
    <variable name="image" type="Drawable"/>
    <variable name="note"  type="String"/>
</data>

將在綁定中生成setter和getters:

public abstract com.example.User getUser();
public abstract void setUser(com.example.User user);
public abstract Drawable getImage();
public abstract void setImage(Drawable image);
public abstract String getNote();
public abstract void setNote(String note);
6.4ViewStubs

ViewStub與正常view有些不同沛豌。他們從不可見(jiàn)的時(shí)候開(kāi)始萝喘,當(dāng)他們要么變得可見(jiàn)時(shí),或者被明確地告知inflate時(shí),他們通過(guò)inflate另一種布局來(lái)取代布局阁簸。

由于ViewStub本質(zhì)上從View層次消失爬早,綁定對(duì)象中的View也必須消失以允許收集。因?yàn)?code>view是最終的启妹,所以一個(gè)ViewStubProxy對(duì)象代替了這個(gè)ViewStub視圖筛严,當(dāng)開(kāi)發(fā)者存在的時(shí)候,它允許開(kāi)發(fā)人員訪問(wèn)ViewStub饶米,并且在ViewStubinflate時(shí)也可以訪問(wèn)inflate的View層次結(jié)構(gòu)桨啃。

當(dāng)inflate另一個(gè)布局時(shí),必須為新的布局建立綁定檬输。因此照瘾,ViewStubProxy一定監(jiān)聽(tīng)ViewStubViewStub.OnInflateListener,同時(shí)建立綁定丧慈。由于只有一個(gè)可以存在遗嗽,所以ViewStubProxy允許開(kāi)發(fā)者設(shè)置一個(gè)OnInflateListener肺然,在建立綁定之后它將被調(diào)用

6.5高級(jí)綁定
動(dòng)態(tài)變量

有時(shí),特定的綁定類是不知道的,例如氮昧,RecyclerView.Adapter針對(duì)任意布局的操作將不知道具體的綁定類臭墨。它仍然必須分配綁定值onBindViewHolder(VH, int)赘来。

在這個(gè)例子中旭贬,RecyclerView綁定的所有布局都有一個(gè)“item”變量。所述的BindingHolder具有getBinding方法返回基礎(chǔ)的ViewDataBinding吟税。

public void onBindViewHolder(BindingHolder holder, int position) {
   final T item = mItems.get(position);
   holder.getBinding().setVariable(BR.item, item);
   holder.getBinding().executePendingBindings();
}
6.6 立即綁定

當(dāng)變量或可觀察對(duì)象變化時(shí)凹耙,綁定將被安排在下一幀之前改變。但有時(shí)候肠仪,綁定必須立即執(zhí)行肖抱。要強(qiáng)制執(zhí)行,請(qǐng)使用該executePendingBindings()方法藤韵。

6.7后臺(tái)線程

只要不是集合虐沥,就可以在后臺(tái)線程中更改數(shù)據(jù)模型。數(shù)據(jù)綁定將在評(píng)估時(shí)本地化每個(gè)變量/字段泽艘,以避免任何并發(fā)問(wèn)題欲险。

7. 屬性Setters

每當(dāng)綁定值發(fā)生變化時(shí),生成的綁定類必須使用綁定表達(dá)式在視圖上調(diào)用setter方法匹涮。數(shù)據(jù)綁定框架可以自定義調(diào)用哪個(gè)方法來(lái)設(shè)置值天试。

7.1 自動(dòng) Setters

對(duì)于一個(gè)屬性,數(shù)據(jù)綁定試圖找到方法setAttribute然低。屬性的命名空間并不重要喜每,只有屬性名稱本身才是重點(diǎn)务唐。

例如,與TextView屬性關(guān)聯(lián)的表達(dá)式 android:text將查找setText(String)带兜。如果表達(dá)式返回一個(gè)int枫笛,那么數(shù)據(jù)綁定將搜索一個(gè)setText(int)方法。請(qǐng)注意讓表達(dá)式返回正確的類型刚照,如果需要的話就進(jìn)行轉(zhuǎn)換刑巧。請(qǐng)注意,即使給定名稱不存在任何屬性无畔,數(shù)據(jù)綁定也可以工作啊楚。然后,您可以使用數(shù)據(jù)綁定輕松地為任何‘創(chuàng)建’的屬性進(jìn)行setter浑彰。例如恭理,support DrawerLayout沒(méi)有任何屬性,但是有很多setter郭变。您可以使用自動(dòng)設(shè)置器來(lái)使用其中的一個(gè)颜价。

<android.support.v4.widget.DrawerLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:scrimColor="@{@color/scrim}"
    app:drawerListener="@{fragment.drawerListener}"/>
7.2重命名Setters

一些擁有setters方法的屬性與名稱不符合。對(duì)于這些方法饵较,屬性可能通過(guò)BindingMethods注釋與setter相關(guān)聯(lián)拍嵌。這必須與一個(gè)類相關(guān)聯(lián)遭赂,并包含BindingMethod注釋循诉,每個(gè)重命名的方法一個(gè)。例如撇他,android:tint屬性確實(shí)與setImageTintList(ColorStateList)關(guān)聯(lián)茄猫,而不是 setTint

@BindingMethods({
       @BindingMethod(type = "android.widget.ImageView",
                      attribute = "android:tint",
                      method = "setImageTintList"),
})

開(kāi)發(fā)人員不太可能需要重命名setter;android框架的屬性已經(jīng)實(shí)現(xiàn)了困肩。

7.3自定義setters

一些屬性需要自定義綁定邏輯划纽。例如,android:paddingLeft 屬性沒(méi)有關(guān)聯(lián)的setter锌畸。相反勇劣,setPadding(left, top, right, bottom)存在。帶BindingAdapter注釋的靜態(tài)綁定適配器方法,允許開(kāi)發(fā)人員定制如何調(diào)用屬性的setter潭枣。

Android屬性已經(jīng)創(chuàng)建BindingAdapter比默。例如,這里是一個(gè)用于paddingLeft

@BindingAdapter("android:paddingLeft")
public static void setPaddingLeft(View view, int padding) {
   view.setPadding(padding,
                   view.getPaddingTop(),
                   view.getPaddingRight(),
                   view.getPaddingBottom());
}

綁定適配器對(duì)其他類型的自定義非常有用盆犁。例如命咐,一個(gè)自定義的加載器可以被調(diào)用脫機(jī)線程來(lái)加載一個(gè)圖像。
當(dāng)發(fā)生沖突時(shí)谐岁,開(kāi)發(fā)人員創(chuàng)建的綁定適配器將覆蓋數(shù)據(jù)綁定默認(rèn)適配器醋奠。

您也可以讓適配器接收多個(gè)參數(shù)榛臼。

@BindingAdapter({"bind:imageUrl", "bind:error"})
public static void loadImage(ImageView view, String url, Drawable error) {
   Picasso.with(view.getContext()).load(url).error(error).into(view);
}
---
<ImageView app:imageUrl="@{venue.imageUrl}"
app:error="@{@drawable/venueError}"/>

如果imageUrlerror都用于ImageView且imageUrl是字符串,并且errordrawable窜司,則將調(diào)用此適配器沛善。

  • 自定義名稱空間在匹配過(guò)程中被忽略。
  • 您也可以為android命名空間編寫(xiě)適配器塞祈。

綁定適配器方法可以選擇性的在其處理程序中使用舊值路呜。采用新舊價(jià)值的方法,首先應(yīng)該擁有屬性的舊值织咧,其次是新的值:

@BindingAdapter("android:paddingLeft")
public static void setPaddingLeft(View view, int oldPadding, int newPadding) {
   if (oldPadding != newPadding) {
       view.setPadding(newPadding,
                       view.getPaddingTop(),
                       view.getPaddingRight(),
                       view.getPaddingBottom());
   }
}

事件處理程序只能用于接口或一個(gè)有抽象方法的抽象類胀葱。例如:

@BindingAdapter("android:onLayoutChange")
public static void setOnLayoutChangeListener(View view, View.OnLayoutChangeListener oldValue,
       View.OnLayoutChangeListener newValue) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        if (oldValue != null) {
            view.removeOnLayoutChangeListener(oldValue);
        }
        if (newValue != null) {
            view.addOnLayoutChangeListener(newValue);
        }
    }
}

當(dāng)一個(gè)監(jiān)聽(tīng)器有多個(gè)方法時(shí),它必須被分成多個(gè)監(jiān)聽(tīng)器笙蒙。比如View.OnAttachStateChangeListener有兩種方法:onViewAttachedToWindow()onViewDetachedFromWindow()抵屿。然后我們必須創(chuàng)建兩個(gè)接口來(lái)區(qū)分它們的屬性和處理程序。

@TargetApi(VERSION_CODES.HONEYCOMB_MR1)
public interface OnViewDetachedFromWindow {
    void onViewDetachedFromWindow(View v);
}

@TargetApi(VERSION_CODES.HONEYCOMB_MR1)
public interface OnViewAttachedToWindow {
    void onViewAttachedToWindow(View v);
}

因?yàn)楦囊粋€(gè)偵聽(tīng)器也會(huì)影響另一個(gè)偵聽(tīng)器捅位,所以我們必須有三個(gè)不同的綁定適配器轧葛,一個(gè)用于每個(gè)屬性,另一個(gè)用于兩個(gè)艇搀,如果它們都被設(shè)置尿扯。

@BindingAdapter("android:onViewAttachedToWindow")
public static void setListener(View view, OnViewAttachedToWindow attached) {
    setListener(view, null, attached);
}

@BindingAdapter("android:onViewDetachedFromWindow")
public static void setListener(View view, OnViewDetachedFromWindow detached) {
    setListener(view, detached, null);
}

@BindingAdapter({"android:onViewDetachedFromWindow", "android:onViewAttachedToWindow"})
public static void setListener(View view, final OnViewDetachedFromWindow detach,
        final OnViewAttachedToWindow attach) {
    if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) {
        final OnAttachStateChangeListener newListener;
        if (detach == null && attach == null) {
            newListener = null;
        } else {
            newListener = new OnAttachStateChangeListener() {
                @Override
                public void onViewAttachedToWindow(View v) {
                    if (attach != null) {
                        attach.onViewAttachedToWindow(v);
                    }
                }

                @Override
                public void onViewDetachedFromWindow(View v) {
                    if (detach != null) {
                        detach.onViewDetachedFromWindow(v);
                    }
                }
            };
        }
        final OnAttachStateChangeListener oldListener = ListenerUtil.trackListener(view,
                newListener, R.id.onAttachStateChangeListener);
        if (oldListener != null) {
            view.removeOnAttachStateChangeListener(oldListener);
        }
        if (newListener != null) {
            view.addOnAttachStateChangeListener(newListener);
        }
    }
}

上面的例子比正常情況稍微復(fù)雜,因?yàn)閂iew使用add和remove來(lái)代替View.OnAttachStateChangeListener的set方法android.databinding.adapters.ListenerUtil類可以幫助跟蹤以前的監(jiān)聽(tīng)焰雕,讓他們可以在綁定Adaper中被刪除的衷笋。

通過(guò)用@TargetApi(VERSION_CODES.HONEYCOMB_MR1)注釋OnViewDetachedFromWindowOnViewAttachedToWindow接口,數(shù)據(jù)綁定代碼生成器知道監(jiān)聽(tīng)器只在Honeycomb MR1和新設(shè)備生成矩屁;同樣的情況在addOnAttachStateChangeListener(View.OnAttachStateChangeListener)上發(fā)生辟宗。

8. 轉(zhuǎn)換器

8.1對(duì)象轉(zhuǎn)換

從綁定表達(dá)式返回一個(gè)對(duì)象時(shí),將從自動(dòng)吝秕,重命名和自定義setter中選擇一個(gè)setter泊脐。該對(duì)象將被轉(zhuǎn)換為所選setter的參數(shù)類型。

這對(duì)于那些使用ObservableMaps來(lái)保存數(shù)據(jù)的人來(lái)說(shuō)非常方便烁峭。例如:

<TextView
   android:text='@{userMap["lastName"]}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

將返回一個(gè)userMap對(duì)象容客,并且將對(duì)象自動(dòng)轉(zhuǎn)換為setText(CharSequence)中的參數(shù)類型。當(dāng)參數(shù)類型可能混淆時(shí)约郁,開(kāi)發(fā)人員需要在表達(dá)式中輸入缩挑。

8.2 自定義轉(zhuǎn)換

有時(shí)轉(zhuǎn)換應(yīng)該在特定類型之間自動(dòng)進(jìn)行。例如棍现,設(shè)置背景時(shí):

<View
   android:background="@{isError ? @color/red : @color/white}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

在這里调煎,背景需要一個(gè)Drawable,但顏色是一個(gè)integer己肮。不管期望 Drawable或是返回一個(gè)integer士袄,int應(yīng)該被轉(zhuǎn)換成一個(gè)ColorDrawable悲关。這個(gè)轉(zhuǎn)換是通過(guò)一個(gè)帶有BindingConversion注解的靜態(tài)方法完成的:

@BindingConversion
public static ColorDrawable convertColorToDrawable(int color) {
   return new ColorDrawable(color);
}

請(qǐng)注意,轉(zhuǎn)換只發(fā)生在setter級(jí)別娄柳,所以不允許混合類型如下所示:

<View
   android:background="@{isError ? @drawable/error : @color/white}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>
9. Android Studio支持?jǐn)?shù)據(jù)綁定

Android Studio支持?jǐn)?shù)據(jù)綁定代碼的許多代碼編輯功能寓辱。例如,它支持?jǐn)?shù)據(jù)綁定表達(dá)式的以下功能:

  • 語(yǔ)法高亮顯示
  • 表達(dá)式語(yǔ)言語(yǔ)法錯(cuò)誤的標(biāo)記
  • XML代碼完成
  • 參考文獻(xiàn)赤拒,包括導(dǎo)航(如導(dǎo)航到聲明)和 快速文檔的參考

注意:數(shù)組和 泛型類型(如Observable類)可能會(huì)在沒(méi)有錯(cuò)誤時(shí)秫筏,顯示錯(cuò)誤。

預(yù)覽窗格顯示數(shù)據(jù)綁定表達(dá)式的默認(rèn)值(如果提供)挎挖。在下面的示例摘錄了布局XML文件中的元素后这敬,“預(yù)覽”窗口將在TextView中顯示PLACEHOLDER默認(rèn)的文本值。

<TextView android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@{user.firstName, default=PLACEHOLDER}"/>

如果需要在項(xiàng)目設(shè)計(jì)階段顯示默認(rèn)值蕉朵,則還可以使用工具屬性而不是默認(rèn)表達(dá)式值崔涂,如 Design Time Layout Attributes中所述。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末始衅,一起剝皮案震驚了整個(gè)濱河市冷蚂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌汛闸,老刑警劉巖蝙茶,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異诸老,居然都是意外死亡隆夯,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門孕锄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吮廉,“玉大人苞尝,你說(shuō)我怎么就攤上這事畸肆。” “怎么了宙址?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵轴脐,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我抡砂,道長(zhǎng)大咱,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任注益,我火速辦了婚禮碴巾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丑搔。我一直安慰自己厦瓢,他們只是感情好提揍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著煮仇,像睡著了一般劳跃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上浙垫,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天刨仑,我揣著相機(jī)與錄音,去河邊找鬼夹姥。 笑死杉武,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的辙售。 我是一名探鬼主播艺智,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼圾亏!你這毒婦竟也來(lái)了十拣?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤志鹃,失蹤者是張志新(化名)和其女友劉穎夭问,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體曹铃,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缰趋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了陕见。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秘血。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖评甜,靈堂內(nèi)的尸體忽然破棺而出灰粮,到底是詐尸還是另有隱情,我是刑警寧澤忍坷,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布粘舟,位于F島的核電站,受9級(jí)特大地震影響佩研,放射性物質(zhì)發(fā)生泄漏柑肴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一旬薯、第九天 我趴在偏房一處隱蔽的房頂上張望晰骑。 院中可真熱鬧,春花似錦绊序、人聲如沸硕舆。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)岗宣。三九已至蚂会,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間耗式,已是汗流浹背胁住。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留刊咳,地道東北人彪见。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像娱挨,于是被迫代替她去往敵國(guó)和親余指。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,077評(píng)論 25 707
  • 2017.8.15 初次添加2017.12.20 更新BindingMethod注解 如果你是第一次使用強(qiáng)烈推薦你...
    談小龍閱讀 514評(píng)論 0 1
  • 1.前言 不知道是否還記得前段時(shí)間講得Android三種主流開(kāi)發(fā)框架跷坝,要是忘了酵镜,可以回顧一下。當(dāng)時(shí)提到了MVVM框...
    lanceJin閱讀 895評(píng)論 0 7
  • 星期一終于到了柴钻。我期盼已久的旅行就要開(kāi)始了淮韭!我特別高興特別興奮。我們一行五個(gè)人贴届,有我的小閨蜜和我們一家三口靠粪,還有她...
    劉玥妙閱讀 445評(píng)論 0 2
  • 博物館回憶錄 一位中年婦女,笑著打趣道:“這可以寫(xiě)進(jìn)我的書(shū)里”毫蚓,順著她的目光有一位年輕女孩占键,但看起來(lái)很邋遢,穿著土...
    戴眼鏡的灰熊閱讀 175評(píng)論 0 0