Jetpack學習2—布局&表達式
概覽
Data Binding Library
Data Binding Library是一個支持庫搔课,它允許您使用聲明格式(而不是編程方式)將布局中的UI組件綁定到應用程序中的數(shù)據(jù)源。
布局通常在帶有調(diào)用UI框架方法的代碼的活動中定義蛾茉。例如,下面的代碼調(diào)用findViewById()
來查找TextView
小部件并將其綁定到viewModel
變量的userName
屬性:
TextView textView = findViewById(R.id.sample_text);
textView.setText(viewModel.getUserName());
下面的示例展示如何使用數(shù)據(jù)綁定庫在布局文件中直接為小部件分配文本锣枝。這樣就不需要調(diào)用上面所示的任何Java代碼扫尺。注意在賦值表達式中使用@{}語法:
<TextView
android:text="@{viewmodel.userName}" />
布局文件中的綁定組件允許您刪除Activity中的許多UI框架調(diào)用启昧,從而使它們更簡單、更易于維護疆柔。這還可以提高應用程序的性能咒精,幫助防止內(nèi)存泄漏和空指針異常。
Using the Data Binding Library
使用以下頁面學習如何在Android應用程序中使用數(shù)據(jù)綁定庫旷档。
? 了解如何使開發(fā)環(huán)境準備好使用數(shù)據(jù)綁定庫模叙,包括Android Studio中對數(shù)據(jù)綁定代碼的支持。
? 表達式語言允許您編寫將變量連接到布局中的視圖的表達式鞋屈。數(shù)據(jù)綁定庫自動生成將布局中的視圖與數(shù)據(jù)對象綁定所需的類向楼。該庫提供了導入、變量等特性谐区,并包括可以在布局中使用的特性湖蜕。
? 這個庫的這些特性與您現(xiàn)有的布局無縫地共存。例如宋列,表達式中可以使用的綁定變量定義在一個數(shù)據(jù)元素中昭抒,該數(shù)據(jù)元素是UI布局的根元素的兄弟元素。這兩個元素都被包裝在一個布局元素中炼杖,如下面的例子所示:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewmodel"
type="com.myapp.data.ViewModel" />
</data>
<ConstraintLayout... /> <!-- UI layout's root element -->
</layout>
? 數(shù)據(jù)綁定庫提供了類和方法來方便地觀察數(shù)據(jù)的變化灭返。當?shù)讓訑?shù)據(jù)源發(fā)生更改時,您不必擔心刷新UI坤邪。你可以讓你的變量或它們的屬性可見熙含。該庫允許您使對象、字段或集合可觀察艇纺。
? Data Binding Library生成用于訪問布局的變量和視圖的綁定類怎静。這個頁面向您展示了如何使用和定制生成的綁定類。
? 對于每個布局表達式黔衡,都有一個綁定適配器進行框架調(diào)用蚓聘,以設置相應的屬性或監(jiān)聽器。例如盟劫,綁定適配器可以調(diào)用setText()方法來設置文本屬性夜牡,或者調(diào)用setOnClickListener()方法來向單擊事件添加監(jiān)聽器。您可以在android.databinding中使用最常見的綁定適配器侣签,例如本文示例中使用的android:text屬性的適配器塘装。適配器包急迂。有關常見綁定適配器的列表,請參見adapters蹦肴。您還可以創(chuàng)建自定義適配器袋毙,如下面的示例所示:
@BindingAdapter("app:goneUnless")
fun goneUnless(view: View, visible: Boolean) {
view.visibility = if (visible) View.VISIBLE else View.GONE
}
? Android支持庫包括架構組件,您可以使用它們來設計健壯冗尤、可測試和可維護的應用程序听盖。您可以使用帶有數(shù)據(jù)綁定庫的體系結構組件來進一步簡化UI的開發(fā)。
? 數(shù)據(jù)綁定庫支持雙向數(shù)據(jù)綁定裂七。這種類型的綁定使用的符號支持接收屬性的數(shù)據(jù)更改并同時監(jiān)聽該屬性的用戶更新皆看。
額外的資源
開始
了解如何使開發(fā)環(huán)境準備好使用數(shù)據(jù)綁定庫背零,包括Android Studio中對數(shù)據(jù)綁定代碼的支持腰吟。
數(shù)據(jù)綁定庫提供了靈活性和廣泛的兼容性——它是一個支持庫,所以您可以在運行Android 4.0 (API級別14)或更高的設備上使用它徙瓶。
建議在你的項目中使用最新的Android插件Gradle毛雇。但是,1.5.0及更高版本支持數(shù)據(jù)綁定侦镇。有關更多信息灵疮,請參見如何更新Gradle的Android插件。
構建環(huán)境
要開始數(shù)據(jù)綁定,請從Android SDK管理器中的支持存儲庫中下載該庫。有關更多信息蚌本,請參見更新IDE和SDK工具内地。
要將應用程序配置為使用數(shù)據(jù)綁定盔腔,請將dataBinding
元素添加app模塊中的build.gradle
文件,如下圖所示:
android {
...
dataBinding {
enabled = true
}
}
注意:必須為依賴使用數(shù)據(jù)綁定的庫的應用程序模塊配置數(shù)據(jù)綁定,即使應用程序模塊不直接使用數(shù)據(jù)綁定。
Android Studio支持數(shù)據(jù)綁定
Android Studio支持許多數(shù)據(jù)綁定代碼的編輯功能羡棵。例如,它支持以下數(shù)據(jù)綁定表達式的特性:
注意:數(shù)組和泛型類型(如Observable類)可能會不正確地顯示錯誤皂冰。
布局編輯器中的預覽窗格顯示數(shù)據(jù)綁定表達式的默認值(如果提供的話)。例如啊犬,預覽窗格會在下面的示例中聲明的TextView小部件上顯示my_default值:
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName, default=my_default}"/>
如果您只需要在項目的設計階段顯示默認值灼擂,則可以使用tools屬性而不是默認表達式值,如Tools Attributes Reference觉至。
用于綁定類的新數(shù)據(jù)綁定編譯器
Android Gradle plugin version 3.1.0-alpha06包含一個新的數(shù)據(jù)綁定編譯器,用于生成綁定類睡腿。新編譯器遞增地創(chuàng)建綁定類语御,這在大多數(shù)情況下加快了構建過程峻贮。有關綁定類的更多信息,請參見 Generated binding classes应闯。
以前版本的數(shù)據(jù)綁定編譯器在編譯托管代碼的相同步驟中生成綁定類纤控。如果托管代碼無法編譯,您可能會收到多個錯誤報告碉纺,說明沒有找到綁定類船万。新的數(shù)據(jù)綁定編譯器通過在托管編譯器構建應用程序之前生成綁定類來防止這些錯誤。
要啟用新的數(shù)據(jù)綁定編譯器骨田,請在gradle.properties
中添加以下選項:
android.databinding.enableV2=true
您還可以在gradle命令中啟用新的編譯器耿导,方法是添加以下參數(shù):
-Pandroid.databinding.enableV2=true
注意:Android Plugin 3.1中的新數(shù)據(jù)綁定編譯器不向后兼容。您需要生成具有此功能的所有綁定類态贤,以便利用增量編譯舱呻。然而,Android Plugin 3.2中的新編譯器與以前版本生成的綁定類是兼容的悠汽。默認情況下箱吕,3.2版中的新編譯器是啟用的。
在啟用新的數(shù)據(jù)綁定編譯器時柿冲,將應用以下行為更改:
- Android Gradle插件在編譯托管代碼之前為你的布局生成綁定類茬高。
- 如果一個布局包含在多個目標資源配置中,數(shù)據(jù)綁定庫將使用android.view.View作為共享相同資源id但不共享視圖類型的所有視圖的默認視圖類型假抄。
- 庫模塊的綁定類被編譯并打包到相應的Android Archive (AAR)文件中雅采。依賴于這些庫模塊的應用程序模塊不再需要重新生成綁定類。有關AAR文件的更多信息慨亲,請參見創(chuàng)建Android庫婚瓜。
- 模塊的綁定適配器不再能夠更改模塊依賴項的適配器的行為。綁定適配器只影響其自身模塊中的代碼和模塊的使用者刑棵。
布局和綁定表達式
表達式語言允許您編寫處理視圖分派的事件的表達式巴刻。數(shù)據(jù)綁定庫自動生成將布局中的視圖與數(shù)據(jù)對象綁定所需的類。
數(shù)據(jù)綁定布局文件略有不同蛉签,首先是布局的根標記胡陪,然后是數(shù)據(jù)元素和視圖根元素。這個視圖元素是您在非綁定布局文件中的根元素碍舍。下面的代碼顯示了一個示例布局文件:
<?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中的user變量描述了可以在此布局中使用的屬性柠座。
<variable name="user" type="com.example.User" />
布局中的表達式使用“@{}”語法在屬性屬性中編寫。在這里片橡,TextView文本被設置為用戶變量的firstName屬性:
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}" />
注意:布局表達式應該保持小而簡單妈经,因為它們不能進行單元測試,并且IDE支持有限。為了簡化布局表達式吹泡,可以使用自定義綁定適配器骤星。
數(shù)據(jù)對象
現(xiàn)在讓我們假設您有一個普通的對象來描述用戶實體:
data class User(val firstName: String, val lastName: String)
這種類型的對象具有永不更改的數(shù)據(jù)。在應用程序中爆哑,很常見的情況是數(shù)據(jù)只讀取一次洞难,以后不會更改。也可以使用遵循一組約定的對象揭朝,例如Java中訪問器方法的使用队贱,如下面的示例所示:
// Not applicable in Kotlin.
data class User(val firstName: String, val lastName: String)
從數(shù)據(jù)綁定的角度來看,這兩個類是等價的潭袱。@{user.firstName}
用于該android:text
屬性的表達式訪問firstName
前一類中的字段和getFirstName()
后一類中的 方法柱嫌。或者敌卓,firstName()
如果存在該方法慎式,也可以解決。
綁定數(shù)據(jù)
為每個布局文件生成一個綁定類趟径。默認情況下瘪吏,類的名稱基于布局文件的名稱,將其轉(zhuǎn)換為Pascal大小寫并向其添加Binding后綴蜗巧。上面的布局文件名是activity_main.xml掌眠,因此相應生成的類是ActivityMainBinding。該類保存從布局屬性(例如幕屹,用戶變量)到布局視圖的所有綁定蓝丙,并且知道如何為綁定表達式賦值。創(chuàng)建綁定的推薦方法是在擴展布局時進行綁定望拖,如下面的示例所示:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding = DataBindingUtil.setContentView(
this, R.layout.activity_main)
binding.user = User("Test", "User")
}
At runtime, the app displays the Test user in the UI. Alternatively, you can get the view using a LayoutInflater
, as shown in the following example:
val binding: ActivityMainBinding = ActivityMainBinding.inflate(getLayoutInflater())
如果您在Fragment渺尘、ListView或RecyclerView適配器中使用數(shù)據(jù)綁定項,您可能更喜歡使用bindings類或DataBindingUtil類的inflate()
方法说敏,如下面的代碼示例所示:
val listItemBinding = ListItemBinding.inflate(layoutInflater, viewGroup, false)
// or
val listItemBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false)
表達式語言
共同特征
表達式語言看起來很像代碼中的表達式鸥跟。在表達式語言中可以使用以下運算符和關鍵字:
- 數(shù)學的
+ - / * %
- 字符串連接
+
- 合乎邏輯
&& ||
- 二進制
& | ^
- 一元
+ - ! ~
- 轉(zhuǎn)移
>> >>> <<
- 比較
== > < >= <=
(注意<
需要轉(zhuǎn)義為<
) instanceof
- 分組
()
- 文字 - 字符,字符串盔沫,數(shù)字医咨,
null
- 計算
- 方法調(diào)用
- 現(xiàn)場訪問
- 數(shù)組訪問
[]
- 三元運算符
?:
例子:
android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'
缺少的操作符
表達式語法缺少以下操作符:
this
super
new
- 顯式通用調(diào)用
空合并操作符
空合并操作符(??
)如果左操作數(shù)不為空,則選擇左操作數(shù);否則架诞,則選擇右操作數(shù)拟淮。
android:text="@{user.displayName ?? user.lastName}"
這在功能上等同于:
android:text="@{user.displayName != null ? user.displayName : user.lastName}"
屬性引用
表達式可以使用以下格式引用類中的屬性,這與字段谴忧、getter和ObservableField
對象的格式相同:
android:text="@{user.lastName}"
避免空指針異常
生成的數(shù)據(jù)綁定代碼會自動檢查null
值并避免空指針異常很泊。例如角虫,在表達式中@{user.name}
,if user
為null撑蚌,user.name
則賦值為默認值null
上遥。如果您引用user.age
age搏屑,其中age是類型int
争涌,那么數(shù)據(jù)綁定使用默認值0
。
集合
為了方便辣恋,可以使用[]操作符訪問 arrays, lists, sparse lists, 和 maps等公共集合亮垫。
<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]}"
注意:要使XML在語法上正確,您必須轉(zhuǎn)義 <
字符伟骨。例如:而不是 List<String>
你必須寫 List<String>
饮潦。
您還可以使用object.key
表示法引用map中的值。例如携狭,@{map[key]}
在上面的例子中可以替換為 @{map.key}
继蜡。
字符串字面值
您可以使用單引號括起屬性值,這允許您在表達式中使用雙引號逛腿,如以下示例所示:
android:text='@{map["firstName"]}'
也可以使用雙引號來包圍屬性值稀并。這樣做時,字符串文字應該用后引號括起來`:
android:text="@{map[`firstName`]}"
資源
您可以在表達式中使用以下語法訪問資源:
android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"
格式字符串和復數(shù)可以通過提供參數(shù)來計算:
android:text="@{@string/nameFormat(firstName, lastName)}"
android:text="@{@plurals/banana(bananaCount)}"
當復數(shù)帶有多個參數(shù)時单默,應傳遞所有參數(shù):
Have an orange
Have %d oranges
android:text="@{@plurals/orange(orangeCount, orangeCount)}"
有些資源需要顯式的類型引用碘举,如下表所示
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 |
事件處理
數(shù)據(jù)綁定允許您編寫從視圖調(diào)度的表達式處理事件(例如,onClick()
方法)搁廓。事件屬性名稱由監(jiān)聽器方法的名稱確定引颈,但有一些例外。例如境蜕,View.OnClickListener
有一個方法onClick()
蝙场,而這個事件的屬性是android:onClick
。
對于單擊事件粱年,有一些特殊的事件處理程序需要android:onClick
以外的屬性以避免沖突售滤。您可以使用以下屬性來避免這些類型的沖突:
Class | Listener setter | Attribute |
---|---|---|
SearchView |
setOnSearchClickListener(View.OnClickListener) |
android:onSearchClick |
ZoomControls |
setOnZoomInClickListener(View.OnClickListener) |
android:onZoomIn |
ZoomControls |
setOnZoomOutClickListener(View.OnClickListener) |
android:onZoomOut |
您可以使用以下機制來處理事件:
- 方法引用:在表達式中,可以引用符合監(jiān)聽器方法簽名的方法逼泣。當表達式執(zhí)行方法引用時趴泌,數(shù)據(jù)綁定將方法引用和所有者對象包裝在監(jiān)聽器中,并在目標視圖上設置監(jiān)聽器拉庶。如果表達式的值為null嗜憔,則數(shù)據(jù)綁定不會創(chuàng)建監(jiān)聽器,而是設置一個空監(jiān)聽器氏仗。
- 監(jiān)聽器綁定:當事件發(fā)生時執(zhí)行這些lambda表達式吉捶。數(shù)據(jù)綁定總是創(chuàng)建視圖上設置的監(jiān)聽器夺鲜。在分派事件時,監(jiān)聽器執(zhí)行l(wèi)ambda表達式呐舔。
方法引用
事件可以直接綁定到處理程序方法币励,類似于android:onClick
可以分配給活動中的方法的方式。與View
onClick
屬性相比的一個主要優(yōu)點 是表達式在編譯時處理珊拼,因此如果該方法不存在或其簽名不正確食呻,則會收到編譯時錯誤。
方法引用和監(jiān)聽器綁定之間的主要區(qū)別在于澎现,實際的監(jiān)聽器實現(xiàn)是在綁定數(shù)據(jù)時創(chuàng)建的仅胞,而不是在觸發(fā)事件時創(chuàng)建的。如果希望在事件發(fā)生時執(zhí)行表達式剑辫,則應該使用監(jiān)聽器綁定干旧。
要將事件分配給其處理程序,請使用普通綁定表達式妹蔽,其值為要調(diào)用的方法名稱椎眯。例如,請考慮以下示例布局數(shù)據(jù)對象:
public class MyHandlers {
public void onClickFriend(View view) { ... }
}
綁定表達式可以將視圖的單擊監(jiān)聽器分配給onClickFriend()
方法胳岂,如下所示:
<?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>
注意:表達式中方法的簽名必須與監(jiān)聽器對象中方法的簽名完全匹配编整。
監(jiān)聽器綁定
監(jiān)聽器綁定是在事件發(fā)生時運行的綁定表達式。它們與方法引用類似旦万,但它們允許您運行任意數(shù)據(jù)綁定表達式闹击。此功能適用于Gradle版本2.0及更高版本的Android Gradle插件。
在方法引用中成艘,方法的參數(shù)必須與事件偵聽器的參數(shù)匹配赏半。在偵聽器綁定中,只有您的返回值必須與偵聽器的預期返回值匹配(除非它預期為void)淆两。例如断箫,考慮下面的presenter類,它有onSaveClick()方法:
public class Presenter {
public void onSaveClick(Task task){}
}
然后秋冰,您可以將click事件綁定到onSaveClick()
方法仲义,如下所示:
<?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>
當在表達式中使用回調(diào)時,數(shù)據(jù)綁定自動創(chuàng)建必要的偵聽器并為事件注冊它剑勾。當視圖觸發(fā)事件時埃撵,數(shù)據(jù)綁定執(zhí)行給定表達式。與常規(guī)的綁定表達式一樣虽另,在執(zhí)行這些偵聽器表達式時暂刘,仍然可以獲得數(shù)據(jù)綁定的null和線程安全性。
在上面的示例中捂刺,我們尚未定義view
傳遞給的參數(shù)onClick(View)
谣拣。監(jiān)聽器綁定為監(jiān)聽器參數(shù)提供了兩種選擇:您可以忽略方法的所有參數(shù)募寨,也可以命名所有參數(shù)。如果您希望為參數(shù)命名森缠,可以在表達式中使用它們拔鹰。例如,上面的表達式可以寫成如下:
android:onClick="@{(view) -> presenter.onSaveClick(task)}"
或者如果你想在表達式中使用參數(shù)贵涵,它可以這樣工作:
public class Presenter {
public void onSaveClick(View view, Task task){}
}
android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"
您可以使用帶有多個參數(shù)的lambda表達式:
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)}" />
如果您正在偵聽的事件返回的值的類型不是void列肢,那么表達式也必須返回相同類型的值。例如独悴,如果您想要監(jiān)聽長時間單擊事件例书,您的表達式應該返回一個布爾值锣尉。
public class Presenter {
public boolean onLongClick(View view, Task task) { }
}
android:onLongClick="@{(theView) -> presenter.onLongClick(theView, task)}"
如果由于null
對象而無法計算表達式刻炒,則數(shù)據(jù)綁定將返回該類型的默認值。例如自沧,null
對于參考類型坟奥,0
for int
,false
for boolean
等拇厢。
如果需要使用條件表達式(例如爱谁,三元),可以使用void作為符號孝偎。
android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}"
避免復雜的監(jiān)聽
監(jiān)聽器表達式非常強大访敌,可以使您的代碼非常容易閱讀。另一方面衣盾,包含復雜表達式的監(jiān)聽器使您的布局難以閱讀和維護寺旺。這些表達式應該像將可用數(shù)據(jù)從UI傳遞到回調(diào)方法一樣簡單。您應該在從偵聽器表達式調(diào)用的回調(diào)方法中實現(xiàn)任何業(yè)務邏輯势决。
Imports, variables, and includes
數(shù)據(jù)綁定庫提供諸imports, variables, and includes之類的功能阻塑。imports使在布局文件中引用類變得很容易。variables允許您描述可用于綁定表達式的屬性果复。includes讓您在整個應用中復用復雜的布局
Imports
Imports允許您輕松引用布局文件中的類陈莽,就像在代碼中一樣。import
可以在data
元素內(nèi)使用零個或多個元素虽抄。以下代碼示例將View
類導入布局文件:
<data>
<import type="android.view.View"/>
</data>
導入View
類允許您從綁定表達式中引用它走搁。以下示例顯示如何引用View
類的常量VISIBLE
和GONE
常量:
<TextView
android:text="@{user.lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>
Type aliases
當存在類名沖突時,可以將其中一個類重命名為別名迈窟。以下示例將com.example.real.estate
包中的View
類 重命名為Vista
:
<data>
<import type="com.example.User"/>
<import type="java.util.List"/>
<variable name="user" type="User"/>
<variable name="userList" type="List<User>"/>
</data>
注意:Android Studio還沒有處理導入私植,因此導入變量的自動完成可能無法在IDE中工作。您的應用程序仍然可以編譯菠隆,您可以通過在變量定義中使用完全限定名來解決IDE問題兵琳。
還可以使用導入的類型強制轉(zhuǎn)換表達式的一部分狂秘。下面的示例將connection
屬性強制轉(zhuǎn)換為一種類型User
:
<TextView
android:text="@{((User)(user.connection)).lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
在表達式中引用靜態(tài)字段和方法時也可以使用導入的類型。下面的代碼導入MyStringUtils類并引用其capitalize
方法:
<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.lang.*
會自動導入者春。
variables
你可以在data
元素中使用多個variable
元素。每個variable
元素都代表一個屬性清女,該屬性可以在布局中設置钱烟,以便在布局文件中的表達式中使用。下面的示例聲明了用戶嫡丙、圖像和注意變量:
<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>
在編譯時檢查變量類型拴袭,因此如果一個變量實現(xiàn)了Observable
或者是observable collection,那么它應該反映在類型中曙博。如果變量是不實現(xiàn)可Observable
接口的基類或接口拥刻,則不觀察變量。
當不同配置有不同的布局文件時(例如父泳,橫向或縱向)般哼,變量就會被組合起來。這些布局文件之間不能有沖突的變量定義惠窄。
生成的綁定類具有用于每個所描述的變量的setter和getter蒸眠。變量采用默認的代碼值,直到調(diào)用setter null
為參考類型杆融,0
for int
楞卡,false
for boolean
等。
會生成一個名為context的特殊變量脾歇,以便根據(jù)需要在綁定表達式中使用蒋腮。context的值是根視圖的getContext()方法中的上下文對象。上下文變量由具有該名稱的顯式變量聲明覆蓋介劫。
includes
通過使用屬性中的app命名空間和變量名徽惋,可以將變量從包含的布局傳遞到包含的布局的綁定中。下面的示例顯示了name.xml
和contact.xml
布局文件中包含的user
變量:
<?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>
數(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><!-- Doesn't work -->
<include layout="@layout/name"
bind:user="@{user}"/>
<include layout="@layout/contact"
bind:user="@{user}"/>
</merge>
</layout>