DataBinding可以在XML中使用事件的回調方法名作爲屬性名(大部分情況下)來處理View分發的事件。比如說View.OnLongClickListener的回調方法是onLongClick,所以這個事件的屬性名稱就是android:onLongClick。
事件的處理可以有兩種方式:
1. 方法引用:在事件屬性的表達式中調用一個方法,這個方法的簽名必須和事件回調方法簽名一致。當事件回調發生時,就會去轉而調用傳入的這個方法。如果事件表達式爲空,則只會給目標view的事件回調設置一個空的監聽器。
2. 監聽器綁定:屬性值表達式是一個lambda表達式,總會創建一個監聽器來設置到目標view上,事件發生的時候纔會執行這個表達式。
這兩種方式的主要區別是方法引用在綁定時就已經給view設置了相對應的監聽了,而監聽器綁定是方法觸發時纔會去執行表達式設置監聽。
1. 方法引用
跟android:onClick
可以直接引用一個Activity中聲明的方法一樣,事件也可以直接綁定到某個類的方法中,注意所綁定方法的參數必須與事件方法參數一致,同時返回值也必須一致。與View#onClick屬性相比,這種方式的優點在於如果未設置相應回調方法,則編譯期就會報錯,不會等到運行時報錯崩潰。使用示例:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="handlers" type="com.example.MainActivity"/>
<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>
public class MainAcivity extends Activity {
public void onClickFriend(View view) { ... }
}
調用語法可以是@{handlers::onClickFriend}
或者@{handlers.onClickFriend}
。
2. 監聽器綁定
事件發生時纔會執行屬性值裏的表達式。跟方法引用不同的是,表達式內可以寫任意的DataBinding表達式。而且監聽器綁定可以定義不同的參數類型,只要表達式返回值與事件方法返回值一致就可以了,如果事件方法返回值是空,表達式可以不用返回。
監聽器綁定的格式如下:
public class Presenter {
public void onSaveClick(Task task){}
}
<!-- XML -->
<?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>
使用的是lambda表達式,並且lambda表達式必須是表達式的最外層。
上述格式中我們省略了onClick的參數View,監聽器綁定中可以省略所有或者列出所有監聽器的參數。列出所有參數的格式如下:
android:onClick="@{(view) -> presenter.onSaveClick(task)}"
聲明瞭參數之後就可以在表達式中使用:
public class Presenter {
public void onSaveClick(View view, Task task){}
}
<!-- XML -->
android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"
Lambda表達式多個參數的示例:
<CheckBox
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />
注意監聽器綁定的返回值必須與回調方法返回值一致,例如:
public class Presenter {
public boolean onLongClick(View view, Task task){}
}
<!-- XML -->
android:onLongClick="@{(theView) -> presenter.onLongClick(theView, task)}"
假如監聽器方法返回null,則會爲回調方法返回其返回值的默認值。
另外可以在lambda表達式中可以使用void:
android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}"