DataBinding可以在XML中使用事件的回调方法名作为属性名(大部分情况下)来处理View分发的事件。比如说View.OnLongClickListener的回调方法是onLongClick,所以这个事件的属性名称就是android:onLongClick。
事件的处理可以有两种方式:
- 方法引用:在事件属性的表达式中调用一个方法,这个方法的签名必须和事件回调方法签名一致。当事件回调发生时,就会去转而调用传入的这个方法。如果事件表达式为空,则只会给目标view的事件回调设置一个空的监听器。
- 监听器绑定:属性值表达式是一个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}"
网友评论