運算式語言可讓您編寫運算式來處理分派的事件 依觀看次數資料繫結程式庫會自動產生必要的類別 將版面配置中的檢視畫面與資料物件繫結。
資料繫結版面配置檔案稍有不同,且開頭為
layout
,後面是 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
中的 user
變數描述了可在
這個版面配置:
<variable name="user" type="com.example.User" />
版面配置內的運算式會使用
@{}
語法。在以下範例中,
TextView
文字已設為
user
變數的 firstName
屬性:
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}" />
資料物件
假設您有一個用來描述 User
實體的純物件:
Kotlin
data class User(val firstName: String, val lastName: String)
Java
public class User { public final String firstName; public final String lastName; public User(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } }
這類物件含有從未變更的資料。在應用程式中 只讀取一次,之後就不會變更您也可以使用 而是遵循一組慣例的物件,例如在其中使用存取子方法 Java 程式設計語言,如以下範例所示:
Kotlin
// Not applicable in Kotlin. data class User(val firstName: String, val lastName: String)
Java
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; } }
從資料繫結的角度來看,這兩個類別相等。
運算式 @{user.firstName}
android:text
屬性會存取舊類別的 firstName
欄位,
getFirstName()
方法。這個函數也解析為
firstName()
(如果已有此方法)。
繫結資料
系統會為每個版面配置檔案產生繫結類別。根據預設
類別是以版面配置檔案的名稱為基礎,並轉換為 Pascal 命名法,
Binding 後置字串。舉例來說,上述版面配置檔案名稱是
activity_main.xml
,因此對應的產生的繫結類別會是
ActivityMainBinding
。
此類別會保留版面配置屬性的所有繫結,例如,
user
變數—傳送至版面配置的檢視畫面,並知道如何指派值
建立繫結運算式建議您在加載時建立繫結
版面配置,如以下範例所示:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding: ActivityMainBinding = DataBindingUtil.setContentView( this, R.layout.activity_main) binding.user = User("Test", "User") }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); User user = new User("Test", "User"); binding.setUser(user); }
在執行階段,應用程式會在 UI 中顯示 Test 使用者。此外,也可以
並使用
LayoutInflater
,如
範例:
Kotlin
val binding: ActivityMainBinding = ActivityMainBinding.inflate(getLayoutInflater())
Java
ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
如果您在
Fragment
、
ListView
,或
RecyclerView
轉換器,您可能會想使用
inflate()
繫結的方法或
DataBindingUtil
類別,
如以下程式碼範例所示:
Kotlin
val listItemBinding = ListItemBinding.inflate(layoutInflater, viewGroup, false) // or val listItemBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false)
Java
ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false); // or ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
運算式語言
常見功能
運算式語言與代管程式碼中的運算式十分相似。個人中心 以下運算子與關鍵字可用於運算式語言:
- 數學:
+ - / * %
- 字串串連:
+
- 邏輯:
&& ||
- 二進位檔:
& | ^
- 一元:
+ - ! ~
- 調節:
>> >>> <<
- 比較:
== > < >= <=
(<
必須逸出為<
) instanceof
- 分組依據:
()
- 常值,例如字元、字串、數字、
null
- 投放
- 方法呼叫
- 欄位存取權
- 存取陣列:
[]
- 三元運算子:
?:
例如:
android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'
缺少作業
您可使用的運算式語法缺少下列作業 :
this
super
new
- 明確一般叫用
空值共合運算子
空值共乘運算子 (??
) 會選擇不是 null
的左運算元
如果前者是 null
,則為右側:
android:text="@{user.displayName ?? user.lastName}"
這在功能上等同於下列內容:
android:text="@{user.displayName != null ? user.displayName : user.lastName}"
資源參照
運算式可採用下列格式參照類別中的屬性:
這對於欄位、getter 和
ObservableField
敬上
物件:
android:text="@{user.lastName}"
避免空值指標例外狀況
產生的資料繫結程式碼會自動檢查 null
值,並避免
空值指標例外狀況。例如,在 @{user.name}
運算式中,如果
user
為 null,user.name
已被指派的預設值 null
。如果發生以下情況:
參照 user.age
,其中年齡層為 int
類型,然後資料繫結會使用
預設值為 0
。
查看參考資料
運算式可使用下列指令,根據 ID 參照版面配置中的其他檢視區塊 語法:
android:text="@{exampleText.text}"
在以下範例中,TextView
檢視表參照了 EditText
檢視區塊,位於
相同的版面配置:
<EditText
android:id="@+id/example_text"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
<TextView
android:id="@+id/example_output"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{exampleText.text}"/>
焦點頻道
存取常用集合,例如陣列、清單、稀疏清單
為方便起見,請使用 []
運算子。
<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]}"
您也可以使用 object.key
標記法參照對應中的值。適用對象
例如,您可以將上述範例中的 @{map[key]}
替換為
@{map.key}
。
字串常值
你可以使用單引號括住屬性值,這樣您就能使用 運算式包含雙引號,如以下範例所示:
android:text='@{map["firstName"]}'
你也可以使用雙引號括住屬性值。這樣做時
字串常值必須以倒引號 `
括住,如上所示
這裡:
android:text="@{map[`firstName`]}"
資源
運算式可以使用下列語法參照應用程式資源:
android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"
您可以提供參數來評估格式字串和複數:
android:text="@{@string/nameFormat(firstName, lastName)}"
android:text="@{@plurals/banana(bananaCount)}"
android:text="@{@string/example_resource(user.lastName, exampleText.text)}"
複數使用多個參數時,請傳遞所有的參數:
Have an orange
Have %d oranges
android:text="@{@plurals/orange(orangeCount, orangeCount)}"
某些資源需要明確類型評估,如下所示 資料表:
類型 | 一般參考資料 | 運算式參照 |
---|---|---|
String[] |
@array |
@stringArray |
int[] |
@array |
@intArray |
TypedArray |
@array |
@typedArray |
Animator |
@animator |
@animator |
StateListAnimator |
@animator |
@stateListAnimator |
color int |
@color |
@color |
ColorStateList |
@color |
@colorStateList |
事件處理
資料繫結可讓您編寫運算式處理,
資料檢視 (例如
onClick()
敬上
方法。事件屬性名稱取決於事件監聽器方法的名稱。
只有少數例外例如:
View.OnClickListener
有
方法為 onClick()
,因此此事件的屬性為 android:onClick
。
點擊事件有一些特殊的事件處理常式,
屬性,以免衝突。android:onClick
您可以使用
下列屬性,避免發生這類衝突:
類別 | 事件監聽器設定者 | 屬性 |
---|---|---|
SearchView |
setOnSearchClickListener(View.OnClickListener) |
android:onSearchClick |
ZoomControls |
setOnZoomInClickListener(View.OnClickListener) |
android:onZoomIn |
ZoomControls |
setOnZoomOutClickListener(View.OnClickListener) |
android:onZoomOut |
您可以使用這兩種機制,詳情請參閱 之後來處理事件:
- 方法參照:您可以在運算式中使用
符合事件監聽器方法簽名的參照方法。時間
運算式會評估為方法參照,資料繫結會包裝方法
參考和擁有者物件,並設定
目標檢視。如果運算式評估為
null
,則資料繫結不會 請建立事件監聽器,並改為設定null
事件監聽器。 - 事件監聽器繫結:這些是 lambda 運算式, 才會受到評估。資料繫結一律會建立 並會在檢視區塊上設定該接聽程式。傳送事件時, 事件監聽器會評估 lambda 運算式。
方法參考資料
您可以直接將事件繫結至處理常式方法,方法與
指派
將 android:onClick
轉換為
方法。相較於
View
onClick
屬性是
運算式都會在編譯期間處理因此,如果這個方法不存在
,您會收到編譯時間錯誤。
方法參照和事件監聽器繫結之間的主要差異在於 系統會在資料繫結時建立實際的事件監聽器實作項目,而非 事件。發生事件時 請使用事件監聽器繫結。
如要將事件指派給處理常式,請使用一般繫結運算式,並加上 值就是要呼叫的方法名稱。例如,請看以下範例 版面配置資料物件:
Kotlin
class MyHandlers { fun onClickFriend(view: View) { ... } }
Java
public class MyHandlers { public void onClickFriend(View view) { ... } }
繫結運算式可將檢視區塊的點擊事件監聽器指派給
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>
事件監聽器繫結
事件監聽器繫結是一種繫結運算式,會在事件發生時執行。他們 類似於方法的參照,但可讓您執行任意的資料繫結 運算式。這項功能適用於 Gradle 適用的 Android Gradle 外掛程式 2.0 以上版本。
在方法參照中,方法的參數必須與
事件接聽程式。在事件監聽器繫結中,只有回傳值必須與
事件監聽器的預期傳回值 (除非預期值是 void
)。適用對象
例如,假設下列簡報者類別具有 onSaveClick()
方法:
Kotlin
class Presenter { fun onSaveClick(task: Task){} }
Java
public class Presenter { public void onSaveClick(Task task){} }
您可以將點擊事件繫結至 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>
在運算式中使用回呼時,資料繫結會自動建立 ,並註冊該事件給 事件。當檢視區塊觸發 事件,資料繫結會評估給定運算式。如同一般繫結 運算式後,您會取得資料繫結的空值和執行緒安全性,而 系統會評估事件監聽器運算式。
在上述範例中,傳遞至 onClick(View)
的 view
參數
沒有定義事件監聽器繫結提供兩個事件監聽器參數的選擇:
您可以忽略方法中的所有參數,也可以為所有參數命名。偏好
為參數命名,即可在運算式中使用。舉例來說,
可以按照以下方式撰寫前面的運算式:
android:onClick="@{(view) -> presenter.onSaveClick(task)}"
如果您想在運算式中使用參數,請按照下列步驟進行:
Kotlin
class Presenter { fun onSaveClick(view: View, task: Task){} }
Java
public class Presenter { public void onSaveClick(View view, Task task){} }
android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"
此外,您可以使用含有多個參數的 lambda 運算式:
Kotlin
class Presenter { fun onCompletedChanged(task: Task, completed: Boolean){} }
Java
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
的值,那麼
運算式也必須傳回相同類型的值。舉例來說
瞭解輕觸與保留 (長按) 事件,運算式就必須傳回
布林值。
Kotlin
class Presenter { fun onLongClick(view: View, task: Task): Boolean { } }
Java
public class Presenter { public boolean onLongClick(View view, Task task) { } }
android:onLongClick="@{(theView) -> presenter.onLongClick(theView, task)}"
如果因 null
物件而無法評估運算式,資料繫結會傳回
該類型的預設值,例如 null
代表參照類型,0
代表
int
,或為 boolean
的 false
。
如果您需要使用帶有述詞的運算式,例如:
三元組,您可以使用 void
做為符號:
android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}"
避免使用複雜的事件監聽器
事件監聽器運算式的功能很強大,可讓您的程式碼更容易閱讀。每月中的特定幾天 另一方面,包含複雜運算式的事件監聽器會使版面配置更加困難 讀取及維護就像傳送可用的資料一樣,運算式保持簡單 直接從使用者介面傳送至回呼方法。在該頁面內實作任何商業邏輯 您從事件監聽器運算式叫用的回呼方法。
匯入、變數,以及包含
資料繫結程式庫提供匯入、變數和 包括匯入功能可讓您在版面配置檔案中輕鬆參照類別。 變數可讓您描述可在繫結運算式中使用的屬性。 可讓您在應用程式內重複使用複雜的版面配置。
匯入
匯入功能可讓您在版面配置檔案中參照類別,就像在代管程式碼中一樣。
您可以在 data
元素中使用零個或多個 import
元素。
以下程式碼範例會將 View
類別匯入版面配置檔案:
<data>
<import type="android.view.View"/>
</data>
匯入 View
類別後,您就能從繫結運算式中參照該類別。
以下範例說明如何參照
VISIBLE
和
View
類別的 GONE
常數:
<TextView
android:text="@{user.lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>
類型別名
如果課程名稱發生衝突,您可以將其中一個類別重新命名為
別名。以下範例將物件中的 View
類別重新命名
將 com.example.real.estate
套件到 Vista
:
<import type="android.view.View"/>
<import type="com.example.real.estate.View"
alias="Vista"/>
接著,您可以使用 Vista
參照 com.example.real.estate.View
和 View
在版面配置檔案中參照 android.view.View
。
匯入其他課程
您可以在變數和運算式中使用匯入的類型做為類型參照。
以下範例顯示用來做為變數類型的 User
和 List
:
<data>
<import type="com.example.User"/>
<import type="java.util.List"/>
<variable name="user" type="User"/>
<variable name="userList" type="List<User>"/>
</data>
您可以使用匯入的類型來轉換運算式的部分流程。下列
範例會將 connection
屬性轉換為 User
類型:
<TextView
android:text="@{((User)(user.connection)).lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
您也可以在參照靜態欄位和方法時,使用匯入的類型
運算式。下列程式碼會匯入 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.*
。
變數
您可以在 data
元素中使用多個 variable
元素。每項
variable
元素說明可在版面配置上設定的屬性
版面配置。以下範例宣告
user
、image
和 note
變數:
<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>
系統會在編譯期間檢查變數類型,因此,如果變數類型
Observable
或
可觀測的集合
必須反映在類型中如果變數是基礎類別或介面
未實作 Observable
介面,那麼這些變數「不會」
。
當不同設定具有不同的版面配置檔案時 (例如, 橫向或直向),這些變數會合併計算。不得使用 造成這些版面配置檔案之間的變數定義發生衝突。
產生的繫結類別會針對每個上述內容,使用 setter 和 getter
變數。變數會採用預設的代管程式碼值,直到 setter 為止
稱為- null
代表參照類型,0
代表 int
,false
代表
boolean
等
系統會產生名為 context
的特殊變數,用於繫結運算式
將物件的使用中版本還原為舊版
或依需要永久刪除封存版本context
的值是
根層級檢視畫面的 Context
物件
getContext()
方法。
context
變數已由明確變數宣告覆寫
名稱。
包含
您可以將變數從含有容器的
使用應用程式命名空間和屬性中的變數名稱來設定版面配置。
以下範例顯示了 name.xml
和user
contact.xml
版面配置檔案:
<?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>
資料繫結不支援做為合併元素的直接子項使用。 舉例來說,系統不支援下列版面配置:
<?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>