data binding使用簡(jiǎn)介

Data Binding解決了Android UI編程中的一個(gè)痛點(diǎn),官方原生支持MVVM模型可以讓我們?cè)诓桓淖兗扔写a框架的前提下,非常容易的使用這些新特性。

Data Binding庫(kù)不僅靈活而且廣泛兼容- 它是一個(gè)support庫(kù),因此你可以在所有的Android平臺(tái)最低能到Android 2.1(API等級(jí)7+)上使用它。

一、準(zhǔn)備

Android Studio更新到1.3及以上版本

打開(kāi) Preferences,找到 Appearances & Behavior 下的 Updates 選項(xiàng),把 Automatically Check updates for 修改成 Canary Channel。

1433345455749011.png

引入data binding的兩種方式

1.1 在Android SDK Manager的支持庫(kù)里下載該庫(kù)

你的app要使用Data Binding,需要添加Data Binding到gradle構(gòu)建文件里,如下:

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

Data Binding插件將會(huì)在你的項(xiàng)目?jī)?nèi)添加必需提供的以及編譯配置依賴。

1.2 gradle配置依賴

Gradle 版本為 1.2.3。

classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'com.android.databinding:dataBinder:1.0-rc0'

為用到 Data Binding 的模塊添加插件,修改對(duì)應(yīng)的 build.gradle。

apply plugin: 'com.android.databinding'

注意

如果 Module 用到的 buildToolsVersion 高于 22.0.1,比如 23 rc1,那 com.android.databinding:dataBinder 的版本要改為 1.3.0-beta1,否則會(huì)出現(xiàn)如下錯(cuò)誤:


1433345521767514.png

我使用這種方法會(huì)不成功,不知道為甚么。

二、Data Binding Layout文件

2.1 Data binding layout文件有點(diǎn)不同的是:起始根標(biāo)簽是layout,接下來(lái)是一個(gè)data元素及一個(gè)view的根元素。這個(gè)view元素就是沒(méi)有使用data binding的layout文件的根元素。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
  <data>
    <variable
        name="user"
        type="com.example.zhaoyong.databinding.model.User"/>
  </data>
  <FrameLayout
    android:layout_width="match_parent"
    android:background="#44ff0000"
    android:layout_height="wrap_content" >

    <TextView
        android:id="@+id/id_num"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:focusable="true"
        android:text="@{user.name}" />
  </FrameLayout>
</layout>

在data內(nèi)描述了一個(gè)名為user的變量屬性,使其可以在這個(gè)layout中使用:

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

在layout的屬性表達(dá)式寫作@{},下面是一個(gè)TextView的text設(shè)置user name的屬性

<TextView
    android:id="@+id/id_num"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:gravity="center"
    android:focusable="true"
    android:text="@{user.name}" />

2.2 Data對(duì)象

假設(shè)你有一個(gè)user的plain-old Java Object(POJO):

public class User {
  public String name;
  public User(String name) {
    this.name = name;
  }
}

這個(gè)類型的對(duì)象擁有從不改變的數(shù)據(jù)。在app中它是常見(jiàn)的,可以讀取一次并且之后從不改變。當(dāng)然也可以使用JavaBean對(duì)象:

public class User {
  private String name;
  public User(String name) {
    this.name = name;
  }
  public String getName() {
    return this.name;
  }
}

從Data Binding的角度來(lái)看,這兩個(gè)類是等價(jià)的。用于TextView中的android:text屬性的表達(dá)式@{user.name}將訪問(wèn)前者的POJO對(duì)象中的name和后者JavaBean對(duì)象中的getName()方法。

2.3 binding數(shù)據(jù)

默認(rèn)情況下,一個(gè)binding類會(huì)基于layout文件的名稱而產(chǎn)生的,將其轉(zhuǎn)換為Pascal case(首字母大寫的命名規(guī)范)并且添加Binding后綴。上述的layout文件是main_activity.xml,因此生成的類名是MainActivityBinding。此類包含從layout屬性到layout的Views中所有的惡binding(例如user變量),并且它還知道如何給Binding表達(dá)式分配數(shù)值。創(chuàng)建binding的最簡(jiǎn)單方式如下:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

    User user = new User(12, "aaaa");
    binding.setUser(user);
}

就是這樣,運(yùn)行app后,你將會(huì)看到Test User?;蛘吣憧梢酝ㄟ^(guò)如下獲取View:

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

如果你在ListView或者RecyclerView adapter使用Data Binding時(shí),你可能會(huì)使用:

ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup,
false);
//or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);

2.4 事件處理

數(shù)據(jù)綁定允許你編寫表達(dá)式來(lái)處理view分派的事件。事件屬性名字取決于監(jiān)聽(tīng)器方法名字。例如View.OnClickListener有onClick()方法,因此這個(gè)事件的屬性是android:onClick。

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="button"
        android:layout_below="@+id/id_recyclerview"
        android:onClick="@{userViewModel::click}"/>

三、深入Layout文件

3.1 Import

零個(gè)或多個(gè)import元素可能在data元素中使用。這些只用在你的layout文件中添加引用,就像在Java中:

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

現(xiàn)在,View可以使用你的Binding表達(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è)類名可以重命名為alias::

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

這樣,在該layout文件中Vista對(duì)應(yīng)com.example.real.estate.View,而View對(duì)應(yīng)android.view.View。導(dǎo)入的類型可以在Variable和表達(dá)式中使用作為引用來(lái)使用:

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

導(dǎo)入的類型還可以在表達(dá)式中使用static屬性和方法:

<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"/>

3.2 Variables

在data中可以使用任意數(shù)量的variable元素。每一個(gè)variable元素描述了一個(gè)用于layout文件中Binding表達(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>

該Variable類型在編譯時(shí)檢查,因此如果一個(gè)Variable實(shí)現(xiàn)了Observable或observable collection,這應(yīng)該反映在類型中。(譯注:需要查找資料來(lái)理解)如果variable是一個(gè)沒(méi)有實(shí)現(xiàn)Observable接口的基本類或者接口,Variables不會(huì)被observed!

當(dāng)對(duì)于多種配置有不同的layout文件時(shí)(如,橫向或縱向),Variables會(huì)被合并。這些layout文件之間必須不能有沖突的Variable定義。

產(chǎn)生的Binding類對(duì)于每一個(gè)描述的Variables都會(huì)有setter和getter。這些Variables會(huì)使用默認(rèn)的Java值 - null(引用類型)、0(int)、false(boolean)等等,直到調(diào)用setter時(shí)。

3.3 自定義Binding類名稱

默認(rèn)情況下,Binding類的命名是基于所述layout文件的名稱,用大寫開(kāi)頭,除去下劃線()以及()后的第一個(gè)字母大寫,然后添加“Binding”后綴。這個(gè)類將被放置在一個(gè)模塊封裝包里的databinding封裝包下。例如,所述layout文件contact_item.xml將生成ContactItemBinding。如果模塊包是com.example.my.app,那么它將被放置在com.example.my.app.databinding。

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

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

在模塊封裝包的databinding包中會(huì)生成名為ContactItem的Binding類。如果要想讓該類生成在不同的包種,你需要添加前綴.,如下:

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

在這個(gè)情況下,ContactItem類直接在模塊包種生成?;蛘吣憧梢蕴峁┱麄€(gè)包名:

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

3.4 Include

通過(guò)使用application namespace以及在屬性中的Variable名字從容器layout中傳遞Variables到一個(gè)被包含的layout:

<?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.xml以及contact.xml兩個(gè)layout文件中必需要有user variable

3.5 表達(dá)式

*常用表達(dá)式跟Java表達(dá)式很像,以下這些是一樣的:

○ 數(shù)學(xué) + - / * %
○ 字符串連接 +
○ 邏輯 && ||
○ 二進(jìn)制 & | ^
○ 一元運(yùn)算 + - ! ~
○ 移位 >> >>> <<
○ 比較 == > < >= <=
○ instanceof
○ 分組 ()
○ null
○ Cast
○ 方法調(diào)用
○ 數(shù)據(jù)訪問(wèn) []
○ 三元運(yùn)算 ?:

示例:

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

○ this
○ super
○ new
○ 顯式泛型調(diào)用

*Null合并操作

○ ?? - 左邊的對(duì)象如果它不是null,選擇左邊的對(duì)象;或者如果它是null,選擇右邊的對(duì)象:

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

函數(shù)上的寫法如下:

android:text="@{user.displayName != null ? user.displayName : user.lastName}"
*屬性引用

第一個(gè)已經(jīng)在前邊提到了a)Data Binding表達(dá)式:JavaBean引用的簡(jiǎn)短格式。
當(dāng)一個(gè)表達(dá)式引用一個(gè)類的屬性,它仍使用同樣的格式對(duì)于字段、getters以及ObservableFields。

android:text="@{user.lastName}"
*避免 NullPointerException

Data Binding代碼生成時(shí)自動(dòng)檢查是否為nulls來(lái)避免出現(xiàn)null pointer exceptions錯(cuò)誤。例如,在表達(dá)式@{user.name}中,如果user是null,user.name會(huì)賦予它的默認(rèn)值(null)。如果你引用user.age,age是int類型,那么它的默認(rèn)值是0。

*集合

常用的集合:arrays、lists、sparse lists以及maps,為了簡(jiǎn)便都可以使用[]來(lái)訪問(wèn)。

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

當(dāng)使用單引號(hào)包含屬性值時(shí),在表達(dá)式中使用雙引號(hào)很容易:

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

使用雙引號(hào)來(lái)包含屬性值也是可以的。字符串前后需要使用"`":

android:text="@{map[`firstName`]}"
android:text="@{map["firstName"]}"
*Resources

使用正常的表達(dá)式來(lái)訪問(wèn)resources也是可行的:

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

格式化字符串和復(fù)數(shù)可以通過(guò)提供參數(shù)來(lái)判斷

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

當(dāng)復(fù)數(shù)需要多個(gè)參數(shù)時(shí),所有的參數(shù)都會(huì)通過(guò):

Have an orange
Have %d oranges
android:text="@{@plurals/orange(orangeCount, orangeCount)}"

一些資源需要顯式類型判斷:

類型 正常引用 表達(dá)式引用
String[] @array @stringArray
int[] @array @intArray
TypedArray @array @typedArray
Animator @animator @animator
StateListAnimator @animator @stateListAnimator
color int @color @color
ColorStateList @color @colorStateList

四、Data對(duì)象

任何Plain old Java object(PO??JO)可用于Data Binding,但修改POJO不會(huì)導(dǎo)致UI更新。Data Binding的真正能力是當(dāng)數(shù)據(jù)變化時(shí),可以通知給你的Data對(duì)象。有三種不同的數(shù)據(jù)變化通知機(jī)制:Observable對(duì)象、ObservableFields以及observable collections。

當(dāng)這些可觀察Data對(duì)象??綁定到UI,Data對(duì)象屬性的更改后,UI也將自動(dòng)更新。

4.1 Observable 對(duì)象

實(shí)現(xiàn)android.databinding.Observable接口的類可以允許附加一個(gè)監(jiān)聽(tīng)器到Bound對(duì)象以便監(jiān)聽(tīng)對(duì)象上的所有屬性的變化。

Observable接口有一個(gè)機(jī)制來(lái)添加和刪除監(jiān)聽(tīng)器,但通知與否由開(kāi)發(fā)人員管理。為了使開(kāi)發(fā)更容易,一個(gè)BaseObservable的基類為實(shí)現(xiàn)監(jiān)聽(tīng)器注冊(cè)機(jī)制而創(chuàng)建。Data實(shí)現(xiàn)類依然負(fù)責(zé)通知當(dāng)屬性改變時(shí)。這是通過(guò)指定一個(gè)Bindable注解給getter以及setter內(nèi)通知來(lái)完成的。

private static class User extends BaseObservable {
 private String firstName;
 private String lastName;
 @Bindable
 public String getFirstName() {
   return this.firstName;
 }
 @Bindable
 public String getFirstName() {
   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è)Entry。BR類文件會(huì)在模塊包內(nèi)生成。

4.2 Observable 字段

一些小工作會(huì)涉及到創(chuàng)建Observable類,因此那些想要節(jié)省時(shí)間或者幾乎沒(méi)有幾個(gè)屬性的開(kāi)發(fā)者可以使用ObservableFields。ObservableFields是自包含具有單個(gè)字段的observable對(duì)象。它有所有基本類型和一個(gè)是引用類型。要使用它需要在data對(duì)象中創(chuàng)建public 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();

}
就是這樣,要訪問(wèn)該值,使用set和get方法:

user.firstName.set("Google");
int age = user.age.get();

4.3 Observable 集合

一些app使用更多的動(dòng)態(tài)結(jié)構(gòu)來(lái)保存數(shù)據(jù)。Observable集合允許鍵控訪問(wèn)這些data對(duì)象。ObservableArrayMap用于鍵是引用類型,如String。

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

在layout文件中,通過(guò)String鍵可以訪問(wèn)map:

<data>
  <import type="android.databinding.ObservableMap"/>
  <variable name="user" type="ObservableMap<String, Object>"/>
</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"/>

ObservableArrayList用于鍵是整數(shù):

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

在layout文件中,通過(guò)索引可以訪問(wèn)list:

<data>
  <import type="android.databinding.ObservableList"/>
  <import type="com.example.my.app.Fields"/>
  <variable name="user" type="ObservableList<Object>"/>
</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"/>

五、Binding生成

Binding類的生成鏈接了layout中variables與Views。如前面所討論的,Binding的名稱和包名可以定制。所生成的Binding類都擴(kuò)展了android.databinding.ViewDataBinding。

5.1 創(chuàng)建

Binding應(yīng)在inflation之后就立馬創(chuàng)建,以確保View層次結(jié)構(gòu)不在之前打擾layout中的binding到views上的表達(dá)式。有幾個(gè)方法可以綁定到一個(gè)layout。最常見(jiàn)的是在Binding類上使用靜態(tài)方法.inflate方法載入View的層次結(jié)構(gòu)并且綁定到它只需這一步。還有一個(gè)更簡(jiǎn)單的版本,只需要LayoutInflater還有一個(gè)是采用ViewGroup:

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

如果使用不同的機(jī)制載入layout,他可一分開(kāi)綁定:

MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);

有時(shí)Binding不能提前知道,對(duì)于這種情況,可以使用DataBindingUtil類來(lái)創(chuàng)建Binding:

ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId,
parent, attachToParent);
ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);

5.2 帶ID的Views

在layout中對(duì)于每個(gè)帶ID的View會(huì)生成一個(gè)public final字段。Binding在View層次結(jié)構(gòu)上做單一的傳遞,提取帶ID的Views。這種機(jī)制比起某些Views使用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ì)生成如下的Binding類:

public final TextView firstName;
public final TextView lastName;

IDs不像沒(méi)有Data Bindings那樣幾乎沒(méi)有必要,但是仍然會(huì)有一些實(shí)例需要從代碼中訪問(wèn)Views。

5.3 Variables

每個(gè)Variable會(huì)有訪問(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>

它會(huì)在Binding中生成setters和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);

5.4 ViewStubs

xml中的 ViewStub 經(jīng)過(guò) binding 之后會(huì)轉(zhuǎn)換成 ViewStubProxy。
簡(jiǎn)單用代碼說(shuō)明一下,xml 文件與之前的代碼一樣,根節(jié)點(diǎn)改為 layout,在 LinearLayout 中添加一個(gè) ViewStub,添加 ID。

<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
    ...>
    <ViewStub
        android:id="@+id/view_stub"
        android:layout="@layout/view_stub"
        ... />
</LinearLayout>
</layout>

在 Java 代碼中獲取 binding 實(shí)例,為 ViewStubProy 注冊(cè) ViewStub.OnInflateListener 事件,搞定!

binding = DataBindingUtil.setContentView(this, R.layout.activity_view_stub);
binding.viewStub.setOnInflateListener(new ViewStub.OnInflateListener() {
@Override
public void onInflate(ViewStub stub, View inflated) {
    ViewStubBinding binding = DataBindingUtil.bind(inflated);
    User user = new User("fee", "lang");
    binding.setUser(user);
}
});

5.5 Dynamic Variables

以 RecyclerView 為例,Adapter 的 DataBinding 需要?jiǎng)討B(tài)生成,因此我們可以在 onCreateViewHolder 的時(shí)候創(chuàng)建這個(gè) DataBinding,然后在 onBindViewHolder 中獲取這個(gè) DataBinding。

public static class BindingHolder extends RecyclerView.ViewHolder {
  private ViewDataBinding binding;
  public BindingHolder(View itemView) {
    super(itemView);
  }
  public ViewDataBinding getBinding() {
    return binding;
  }
  public void setBinding(ViewDataBinding binding) {
    this.binding = binding;
  }
}
@Override
public BindingHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
ViewDataBinding binding = DataBindingUtil.inflate(
        LayoutInflater.from(viewGroup.getContext()),
        R.layout.list_item,
        viewGroup,
        false);
BindingHolder holder = new BindingHolder(binding.getRoot());
holder.setBinding(binding);
return holder;
}
@Override
public void onBindViewHolder(BindingHolder holder, int position) {
User user = users.get(position);
holder.getBinding().setVariable(BR.user, user);
holder.getBinding().executePendingBindings();
}

注意此處 DataBindingUtil 的用法:

ViewDataBinding binding = DataBindingUtil.inflate(
LayoutInflater.from(viewGroup.getContext()),
R.layout.list_item,
viewGroup,
false);

六、屬性Setters

有了 Data Binding,即使屬性沒(méi)有在 declare-styleable 中定義,我們也可以通過(guò) xml 進(jìn)行賦值操作。 為了演示這個(gè)功能,我自定義了一個(gè) View - UserView,其中 R.styleable.UserView 中只定義了一個(gè) age 屬性,其中 firstName 和 lastName 只有對(duì)應(yīng)的兩個(gè) setter 方法。

只要有 setter 方法就可以這樣為屬性賦值:

<com.liangfeizc.databindingsamples.attributesetters.UserView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/largePadding"
app:onClickListener="@{activity.clickListener}"
app:firstName="@{@string/firstName}"
app:lastName="@{@string/lastName}"
app:age="27" />

onClickListener 也是同樣道理,只不過(guò)我們是在 Activity 中定義了一個(gè) Listener。

七、轉(zhuǎn)換器

在 xml 中為屬性賦值時(shí),如果變量的類型與屬性不一致,通過(guò) DataBinding 可以進(jìn)行轉(zhuǎn)換。

<Button
android:onClick="toggleIsError"
android:text="@{isError.get() ? @color/red : @color/white}"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

只需要定義一個(gè)標(biāo)記了 @BindingConversion 的靜態(tài)方法即可:

@BindingConversion
public static int convertColorToString(int color) {
switch (color) {
    case Color.RED:
        return R.string.red;
    case Color.WHITE:
        return R.string.white;
}
return R.string.app_name;
}

參考

http://www.itdecent.cn/p/b1df61a4df77
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0603/2992.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容