偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Android Data Binding 用戶指南

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

1. 介紹

這篇文章介紹了如何使用Data Binding庫(kù)來(lái)寫(xiě)聲明的layouts文件,并且用最少的代碼來(lái)綁定你的app邏輯和layouts文件。

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

需要:Android Studio 1.3.0-beta1 或更高版本。

 

測(cè)試版本

 

請(qǐng)注意:Data Binding庫(kù)當(dāng)前是測(cè)試版本。在Data Binding處于測(cè)試階段時(shí),開(kāi)發(fā)者應(yīng)該了解以下注意事項(xiàng):

這是旨在生成開(kāi)發(fā)者的反饋功能的測(cè)試版本。它可能包含bugs,或者不適合你的使用案例,所以需要您在使用它時(shí)自擔(dān)風(fēng)險(xiǎn)。即便如此,我們非常希望得到您的反饋!使用issue tracker來(lái)讓我們知道對(duì)于你的使用案例什么可以工作或者不能工作。

 

Data Binding庫(kù)的測(cè)試版本傾向于顯著的改變,包括那些不是與您的應(yīng)用程序兼容的源代碼。即,在未來(lái)可能會(huì)進(jìn)行大量的返工來(lái)更新此庫(kù)。

 

雖然伴有標(biāo)準(zhǔn)Android SDK和Google Play服務(wù)條款適用警告,開(kāi)發(fā)人員可以隨時(shí)發(fā)布內(nèi)置了與Data Binding庫(kù)beta版本的應(yīng)用程序。而且采用新的庫(kù)或工具是一個(gè)相當(dāng)好的主意來(lái)徹底測(cè)試你的應(yīng)用程序。

 

我們?cè)谶@個(gè)時(shí)候才剛剛開(kāi)始與Android Studio的支持。未來(lái)會(huì)有進(jìn)一步的Android Studio的支持。

 

通過(guò)使用Data Binding庫(kù)beta版本,你承認(rèn)這些警告。

 

2. 構(gòu)建環(huán)境

要開(kāi)始使用Data Binding,首先需要在Android SDK Manager的支持庫(kù)里下載該庫(kù)。

請(qǐng)確保您使用的是 Android Studio 的兼容版本。Android Studio的Data Binding 插件需要 Android Studio 1.3.0-beta1 或更高版本。

 

工作環(huán)境

 

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

  1. dependencies { 
  2. classpath "com.android.tools.build:gradle:1.2.3" 
  3. classpath "com.android.databinding:dataBinder:1.0-rc0" 

然后確保jcenter在repositories列表里,如下:

  1. allprojects { 
  2. repositories { 
  3. jcenter() 

在每一個(gè)你想要使用Data Binding的module,添加如下的插件:

apply plugin: ‘com.android.application'

 

apply plugin: 'com.android.databinding'

 

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

 

3. Data Binding Layout 文件

 

Data Binding表達(dá)式

 

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

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <layout xmlns:android="http://schemas.android.com/apk/res/android"
  3. <data> 
  4. <variable name="user" type="com.example.User"/> 
  5. </data> 
  6. <LinearLayout 
  7. android:orientation="vertical" 
  8. android:layout_width="match_parent" 
  9. android:layout_height="match_parent"
  10. <TextView android:layout_width="wrap_content" 
  11. android:layout_height="wrap_content" 
  12. android:text="@{user.firstName}"/> 
  13. <TextView android:layout_width="wrap_content" 
  14. android:layout_height="wrap_content" 
  15. android:text="@{user.lastName}"/> 
  16. </LinearLayout> 
  17. </layout> 

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

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

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

  1. <TextView android:layout_width="wrap_content" 
  2. android:layout_height="wrap_content" 
  3. android:text="@{user.firstName}"/> 

Data對(duì)象

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

  1. public class User { 
  2. public final String firstName; 
  3. public final String lastName; 
  4. public User(String firstName, String lastName) { 
  5. this.firstName = firstName; 
  6. this.lastName = lastName; 

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

  1. public class User { 
  2. private final String firstName; 
  3. private final String lastName; 
  4. public User(String firstName, String lastName) { 
  5. this.firstName = firstName; 
  6. this.lastName = lastName; 
  7. public String getFirstName() { 
  8. return this.firstName; 
  9. public String getLastName() { 
  10. return this.lastName; 

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

 

Binding數(shù)據(jù)

 

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

  1. @Override 
  2. protected void onCreate(Bundle savedInstanceState) { 
  3. super.onCreate(savedInstanceState); 
  4. ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity); 
  5. User user = new User("Test""User"); 
  6. binding.setUser(user); 
  7.  
  8. 就是這樣,運(yùn)行app后,你將會(huì)看到Test User?;蛘吣憧梢酝ㄟ^(guò)如下獲取View: 
  9.  
  10. MainActivityBinding binding = MainActivityBinding.inflate(getLayoutInflater()); 
  11.  
  12. 如果你在ListView或者RecyclerView adapter使用Data Binding時(shí),你可能會(huì)使用: 
  13.  
  14. ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, 
  15. false); 
  16. //or 
  17. ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false); 

#p#

4. 深入 Layout 文件

 

Import

 

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

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

現(xiàn)在,View可以使用你的Binding表達(dá)式:

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

當(dāng)類(lèi)名有沖突時(shí),其中一個(gè)類(lèi)名可以重命名為alias::

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

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

  1. <data> 
  2. <import type="com.example.User"/> 
  3. <import type="java.util.List"/> 
  4. <variable name="user" type="User"/> 
  5. <variable name="userList" type="List<User>"/> 
  6. </data> 

注意:Android Studio還沒(méi)有處理imports,所以自動(dòng)導(dǎo)入Variable在你的IDE不能使用。您的app仍會(huì)正常編譯,你可以在您的Variable定義中使用完全符合規(guī)定的名稱(chēng)來(lái)解決該IDE問(wèn)題。

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

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

  1. <data> 
  2. <import type="com.example.MyStringUtils"/> 
  3. <variable name="user" type="com.example.User"/> 
  4. </data> 
  5. … 
  6. <TextView 
  7. android:text="@{MyStringUtils.capitalize(user.lastName)}" 
  8. android:layout_width="wrap_content" 
  9. android:layout_height="wrap_content"/> 

就像在Java中,java.lang。*是自動(dòng)導(dǎo)入的。

 

Variables

 

在data中可以使用任意數(shù)量的variable元素。每一個(gè)variable元素描述了一個(gè)用于layout文件中Binding表達(dá)式的屬性。

  1. <data> 
  2. <import type="android.graphics.drawable.Drawable"/> 
  3. <variable name="user" type="com.example.User"/> 
  4. <variable name="image" type="Drawable"/> 
  5. <variable name="note" type="String"/> 
  6. </data> 

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

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

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

 

自定義 Binding 類(lèi)名稱(chēng)

 

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

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

  1. <data class="ContactItem"
  2. ... 
  3. </data> 

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

  1. <data class=".ContactItem"
  2. ... 
  3. </data> 

在這個(gè)情況下,ContactItem類(lèi)直接在模塊包種生成。或者你可以提供整個(gè)包名:

  1. <data class="com.example.ContactItem"
  2. ... 
  3. </data> 

Includes

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

 

  1. <?xml version="1.0" encoding="utf-8"?> 
  2.  
  3. <layout xmlns:android="http://schemas.android.com/apk/res/android" 
  4.  
  5. xmlns:bind="http://schemas.android.com/apk/res-auto"
  6.  
  7. <data> 
  8.  
  9. <variable name="user" type="com.example.User"/> 
  10.  
  11. </data> 
  12.  
  13. <LinearLayout 
  14.  
  15. android:orientation="vertical" 
  16.  
  17. android:layout_width="match_parent" 
  18.  
  19. android:layout_height="match_parent"
  20.  
  21. <include layout="@layout/name" 
  22.  
  23. bind:user="@{user}"/> 
  24.  
  25. <include layout="@layout/contact" 
  26.  
  27. bind:user="@{user}"/> 
  28.  
  29. </LinearLayout> 
  30.  
  31. </layout> 

 

 

注意:在name.xml以及contact.xml兩個(gè)layout文件中必需要有user variable

 

表達(dá)式

 

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

數(shù)學(xué) + - / * %

 

字符串連接 +

 

邏輯 && ||

 

二進(jìn)制 & | ^

 

一元運(yùn)算 + - ! ~

 

移位 >> >>> <<

 

比較 == > < >= <=

 

instanceof

 

分組 ()

 

null

 

Cast

 

方法調(diào)用

 

數(shù)據(jù)訪問(wèn) []

 

三元運(yùn)算 ?:

 

示例:

  1. android:text="@{String.valueOf(index + 1)}" 
  2. android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}" 
  3. android:transitionName='@{"image_" + id}' 

缺少的操作

this

 

super

 

new

 

#p#

顯式泛型調(diào)用

 

Null合并操作

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

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

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

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

屬性引用

***個(gè)已經(jīng)在前邊提到了a)Data Binding表達(dá)式:JavaBean引用的簡(jiǎn)短格式。

當(dāng)一個(gè)表達(dá)式引用一個(gè)類(lèi)的屬性,它仍使用同樣的格式對(duì)于字段、getters以及ObservableFields。

  1. android:text="@{user.lastName}" 
  2.  
  3. 避免 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類(lèi)型,那么它的默認(rèn)值是0。

 

集合

 

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

  1. <data> 
  2. <import type="android.util.SparseArray"/> 
  3. <import type="java.util.Map"/> 
  4. <import type="java.util.List"/> 
  5. <variable name="list" type="List<String>"/> 
  6. <variable name="sparse" type="SparseArray<String>"/> 
  7. <variable name="map" type="Map<String, String>"/> 
  8. <variable name="index" type="int"/> 
  9. <variable name="key" type="String"/> 
  10. </data> 
  11. … 
  12. android:text="@{list[index]}" 
  13. … 
  14. android:text="@{sparse[index]}" 
  15. … 
  16. android:text="@{map[key]}" 

字符串

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

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

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

  1. android:text="@{map[`firstName`]}" 
  2. android:text="@{map["firstName"]}" 
  3.  
  4. Resources 

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

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

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

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

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

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

一些資源需要顯式類(lèi)型判斷:

 

類(lèi)型 正常引用 表達(dá)式引用

 

 

 

  1. String[] @array @stringArray 
  2. int[] @array @intArray 
  3. TypedArray @array @typedArray 
  4. Animator @animator @animator 
  5. StateListAnimator @animator @stateListAnimator 
  6. color int @color @color 
  7. ColorStateList @color @colorStateList 

 

 

5. 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)更新。

 

Observable 對(duì)象

 

實(shí)現(xiàn)android.databinding.Observable接口的類(lèi)可以允許附加一個(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的基類(lèi)為實(shí)現(xiàn)監(jiān)聽(tīng)器注冊(cè)機(jī)制而創(chuàng)建。Data實(shí)現(xiàn)類(lèi)依然負(fù)責(zé)通知當(dāng)屬性改變時(shí)。這是通過(guò)指定一個(gè)Bindable注解給getter以及setter內(nèi)通知來(lái)完成的。

  1. private static class User extends BaseObservable { 
  2. private String firstName; 
  3. private String lastName; 
  4. @Bindable 
  5. public String getFirstName() { 
  6. return this.firstName; 
  7. @Bindable 
  8. public String getFirstName() { 
  9. return this.lastName; 
  10. public void setFirstName(String firstName) { 
  11. this.firstName = firstName; 
  12. notifyPropertyChanged(BR.firstName); 
  13. public void setLastName(String lastName) { 
  14. this.lastName = lastName; 
  15. notifyPropertyChanged(BR.lastName); 

在編譯期間,Bindable注解在BR類(lèi)文件中生成一個(gè)Entry。BR類(lèi)文件會(huì)在模塊包內(nèi)生成。如果用于Data類(lèi)的基類(lèi)不能改變,Observable接口通過(guò)方便的PropertyChangeRegistry來(lái)實(shí)現(xiàn)用于儲(chǔ)存和有效地通知監(jiān)聽(tīng)器。

 

Observable 字段

 

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

  1. private static class User extends BaseObservable { 
  2. public final ObservableField<String> firstName = 
  3. new ObservableField<>(); 
  4. public final ObservableField<String> lastName = 
  5. new ObservableField<>(); 
  6. public final ObservableInt age = new ObservableInt(); 

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

user.firstName.set("Google");

 

int age = user.age.get();

 

Observable 集合

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

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

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

  1. <data> 
  2. <import type="android.databinding.ObservableMap"/> 
  3. <variable name="user" type="ObservableMap<String, Object>"/> 
  4. </data> 
  5. … 
  6. <TextView 
  7. android:text='@{user["lastName"]}' 
  8. android:layout_width="wrap_content" 
  9. android:layout_height="wrap_content"/> 
  10. <TextView 
  11. android:text='@{String.valueOf(1 + (Integer)user["age"])}' 
  12. android:layout_width="wrap_content" 
  13. android:layout_height="wrap_content"/> 
  14.  
  15. ObservableArrayList用于鍵是整數(shù): 
  16.  
  17. ObservableArrayList<Object> user = new ObservableArrayList<>(); 
  18. user.add("Google"); 
  19. user.add("Inc."); 
  20. user.add(17); 

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

  1. <data> 
  2. <import type="android.databinding.ObservableList"/> 
  3. <import type="com.example.my.app.Fields"/> 
  4. <variable name="user" type="ObservableList<Object>"/> 
  5. </data> 
  6. … 
  7. <TextView 
  8. android:text='@{user[Fields.LAST_NAME]}' 
  9. android:layout_width="wrap_content" 
  10. android:layout_height="wrap_content"/> 
  11. <TextView 
  12. android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}' 
  13. android:layout_width="wrap_content" 
  14. android:layout_height="wrap_content"/> 
  15.  
  16. 6. Binding生成 

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

 

#p#

創(chuàng)建

 

Binding應(yīng)在inflation之后就立馬創(chuàng)建,以確保View層次結(jié)構(gòu)不在之前打擾layout中的binding到views上的表達(dá)式。有幾個(gè)方法可以綁定到一個(gè)layout。最常見(jiàn)的是在Binding類(lèi)上使用靜態(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)來(lái)創(chuàng)建Binding:

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

帶ID的Views

在layout中對(duì)于每個(gè)帶ID的View會(huì)生成一個(gè)public final字段。Binding在View層次結(jié)構(gòu)上做單一的傳遞,提取帶ID的Views。這種機(jī)制比起某些Views使用findViewById還要快。例如:

  1. <layout xmlns:android="http://schemas.android.com/apk/res/android"
  2. <data> 
  3. <variable name="user" type="com.example.User"/> 
  4. </data> 
  5. <LinearLayout 
  6. android:orientation="vertical" 
  7. android:layout_width="match_parent" 
  8. android:layout_height="match_parent"
  9. <TextView android:layout_width="wrap_content" 
  10. android:layout_height="wrap_content" 
  11. android:text="@{user.firstName}" 
  12. android:id="@+id/firstName"/> 
  13. <TextView android:layout_width="wrap_content" 
  14. android:layout_height="wrap_content" 
  15. android:text="@{user.lastName}" 
  16. android:id="@+id/lastName"/> 
  17. </LinearLayout> 
  18. </layout> 

它會(huì)生成如下的Binding類(lèi):

public final TextView firstName;

 

public final TextView lastName;

 

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

 

Variables

 

每個(gè)Variable會(huì)有訪問(wèn)方法。

  1. <data> 
  2. <import type="android.graphics.drawable.Drawable"/> 
  3. <variable name="user" type="com.example.User"/> 
  4. <variable name="image" type="Drawable"/> 
  5. <variable name="note" type="String"/> 
  6. </data> 

它會(huì)在Binding中生成setters和getters:

  1. public abstract com.example.User getUser(); 
  2. public abstract void setUser(com.example.User user); 
  3. public abstract Drawable getImage(); 
  4. public abstract void setImage(Drawable image); 
  5. public abstract String getNote(); 
  6. public abstract void setNote(String note); 

ViewStubs

ViewStubs跟正常的Views略有不同。他們開(kāi)始時(shí)是不可見(jiàn)的,當(dāng)他們要么設(shè)置為可見(jiàn)或被明確告知要載入時(shí),它們通過(guò)載入另外一個(gè)layout取代了自己。

由于ViewStub基本上從View的層次結(jié)構(gòu)上消失,在Binding對(duì)象的View也必須消失來(lái)允許被收集。因?yàn)閂iews是***的,一個(gè)ViewStubProxy對(duì)象取帶ViewStub,給開(kāi)發(fā)者獲得了ViewStub,當(dāng)它存在以及還可以訪問(wèn)載入的View層次結(jié)構(gòu)時(shí)當(dāng)ViewStub已被載入時(shí)。

當(dāng)載入另一個(gè)layout,為新的布局必需創(chuàng)建一個(gè)Binding。因此,ViewStubProxy必需監(jiān)聽(tīng)ViewStub的OnInflateListener監(jiān)聽(tīng)器并在那個(gè)時(shí)候建立Binding。因?yàn)橹挥幸粋€(gè)可以存在,ViewStubProxy允許開(kāi)發(fā)者在其上設(shè)置一個(gè)OnInflateListener它會(huì)在建立Binding后調(diào)用。

 

Binding進(jìn)階

 

動(dòng)態(tài)Variables

 

有時(shí),不知道具體的Binding類(lèi),例如,一個(gè)RecyclerView適配器對(duì)layouts任意操作并不知道具體的Binding類(lèi)。它仍然必需在onBindViewHolder期間賦值給Binding。

在這個(gè)例子中,該RecyclerView綁定的所有l(wèi)ayouts有一個(gè)“item”的Variable。該BindingHolder有一個(gè)getBinding方法返回ViewDataBinding。

  1. public void onBindViewHolder(BindingHolder holder, int position) { 
  2. final T item = mItems.get(position); 
  3. holder.getBinding().setVariable(BR.item, item); 
  4. holder.getBinding().executePendingBindings(); 

直接Binding

當(dāng)一個(gè)variable或observable變化時(shí),binding會(huì)在下一幀之前被計(jì)劃要改變。有很多次,但是在Binding時(shí)必須立即執(zhí)行。要強(qiáng)制執(zhí)行,使用executePendingBindings()方法。

 

后臺(tái)線程

 

只要它不是一個(gè)集合,你可以在后臺(tái)線程中改變你的數(shù)據(jù)模型。在判斷是否要避免任何并發(fā)問(wèn)題時(shí),Data Binding會(huì)對(duì)每個(gè)Varialbe/field本地化。

 

7. 屬性Setters

 

每當(dāng)綁定值的變化,生成的Binding類(lèi)必須調(diào)用setter方法​​。Data Binding框架有可以自定義賦值的方法。

 

自動(dòng)Setters

 

對(duì)于一個(gè)屬性,Data Binding試圖找到setAttribute方法。與該屬性的namespace并不什么關(guān)系,僅僅與屬性本身名稱(chēng)有關(guān)。

例如,有關(guān)TextView的android:text屬性的表達(dá)式會(huì)尋找一個(gè)setText(String)的方法。如果表達(dá)式返回一個(gè)int,Data Binding會(huì)搜索的setText(int)方法。注意:要表達(dá)式返回正確的類(lèi)型,如果需要的話使用casting。Data Binding仍會(huì)工作即使沒(méi)有給定名稱(chēng)的屬性存在。然后,您可以通過(guò)Data Binding輕松地為任何setter“創(chuàng)造”屬性。例如,DrawerLayout沒(méi)有任何屬性,但大量的setters。您可以使用自動(dòng)setters來(lái)使用其中的一個(gè)。

  1. <android.support.v4.widget.DrawerLayout 
  2. android:layout_width="wrap_content" 
  3. android:layout_height="wrap_content" 
  4. app:scrimColor="@{@color/scrim}" 
  5. app:drawerListener="@{fragment.drawerListener}"/> 

重命名的Setters

一些有setters的屬性按名稱(chēng)并不匹配。對(duì)于這些方法,屬性可以通過(guò)BindingMethods注解相關(guān)聯(lián)。這必須與一個(gè)包含BindingMethod注解的類(lèi)相關(guān)聯(lián),每一個(gè)用于一個(gè)重命名的方法。例如,android:tint屬性與setImageTintList相關(guān)聯(lián),而不與setTint相關(guān)。

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

以上例子,開(kāi)發(fā)者需要重命名setters是不太可能了,android架構(gòu)屬性已經(jīng)實(shí)現(xiàn)了。

 

自定義Setters

 

有些屬性需要自定義綁定邏輯。例如,對(duì)于android:paddingLeft屬性并沒(méi)有相關(guān)setter。相反,setPadding(left, top, right, bottom)是存在在。一個(gè)帶有BindingAdapter注解的靜態(tài)綁定適配器方法允許開(kāi)發(fā)者自定義setter如何對(duì)于一個(gè)屬性的調(diào)用。

Android的屬性已經(jīng)創(chuàng)造了BindingAdapters。舉例來(lái)說(shuō),對(duì)于paddingLeft:

  1. @BindingAdapter("android:paddingLeft"
  2. public static void setPaddingLeft(View view, int padding) { 
  3. view.setPadding(padding, 
  4. view.getPaddingTop(), 
  5. view.getPaddingRight(), 
  6. view.getPaddingBottom()); 

Binding適配器對(duì)其他定制類(lèi)型非常有用。例如,自定義loader可以用來(lái)異步載入圖像。

當(dāng)有沖突時(shí),開(kāi)發(fā)人員創(chuàng)建的Binding適配器將覆蓋Data Binding默認(rèn)適配器。

您也可以創(chuàng)建可以接收多個(gè)參數(shù)的適配器。

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

如果對(duì)于一個(gè)ImageViewimageUrl和error都被使用并且imageUrl是一個(gè)string類(lèi)型以及error是一個(gè)drawable時(shí),該適配器會(huì)被調(diào)用。

匹配的過(guò)程中自定義namespaces將被忽略。

 

你也可以為Android namespaces寫(xiě)適配器。

 

#p#

8. 轉(zhuǎn)換

 

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

 

當(dāng)從Binding表達(dá)式返回一個(gè)對(duì)象,一個(gè)setter會(huì)從自動(dòng)、重命名以及自定義的setters中選擇。該對(duì)象將被轉(zhuǎn)換為所選擇的setter的參數(shù)類(lèi)型。

這是為了方便那些使用ObservableMaps來(lái)保存數(shù)據(jù)。例如:

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

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

 

自定義轉(zhuǎn)換

 

有時(shí)候轉(zhuǎn)換應(yīng)該是自動(dòng)的在特定類(lèi)型之間。例如,設(shè)置背景的時(shí)候:

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

這里,背景需要Drawable對(duì)象,但顏色是一個(gè)整數(shù)。不管何時(shí)有Drawable并且返回值是一個(gè)整數(shù),那么整數(shù)類(lèi)型會(huì)被轉(zhuǎn)換為ColorDrawable。這個(gè)轉(zhuǎn)換是通過(guò)使用帶有BindingConversion注解的靜態(tài)方法完成的:

  1. @BindingConversion 
  2. public static ColorDrawable convertColorToDrawable(int color) { 
  3. return new ColorDrawable(color); 

注意:轉(zhuǎn)換僅僅發(fā)生在setter級(jí)別,因此它是不允許以下混合類(lèi)型:

  1. <View 
  2. android:background="@{isError ? @drawable/error : @color/white}" 
  3. android:layout_width="wrap_content" 
  4. android:layout_height="wrap_content"/>
責(zé)任編輯:chenqingxiang 來(lái)源: 田浩浩_DockOne
相關(guān)推薦

2015-08-11 09:41:58

AndroiddataBinding

2013-12-26 16:59:12

Android開(kāi)發(fā)Android應(yīng)用數(shù)據(jù)綁定Data Bi

2017-05-24 18:00:13

AndroidAndroid DatView

2013-12-04 14:44:41

Android SDK用戶交互

2010-06-09 15:53:30

UML建模

2017-08-05 16:31:51

TiDBTiSpark數(shù)據(jù)庫(kù)

2013-11-27 10:12:11

2010-06-12 17:19:18

UML用戶指南

2009-06-11 13:53:35

jBPM用戶指南

2011-08-02 09:38:25

IOS 用戶設(shè)計(jì)

2011-11-08 18:34:59

Fedora 16桌面配置指南

2012-01-10 13:21:33

Sencha Touc使用data包

2020-09-03 13:20:17

scprsync遷移指南

2011-04-21 15:20:37

iOS設(shè)計(jì)用戶界面iOS

2010-06-13 16:26:10

UML圖

2009-12-17 15:56:34

Rails參數(shù)bind

2010-09-01 11:09:04

無(wú)線局域網(wǎng)

2012-03-29 09:09:59

2017-12-25 09:50:46

Linux邏輯卷管理文件系統(tǒng)

2009-08-27 16:59:20

ASP.NET用戶控件
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)