绑定事件处理方法到view,当view的事件发生时,调用这些方法处理事件。
有两种绑定方法:Method References(方法引用)和Listener Bindings(监听绑定)。
这种方法类似于在布局文件中定义android:onClick属性,然后在activity中定义相关的方法,但是要强大得多,在编译的时候就绑定了,这样不用担心运行时报错了(activity那种是运行时报错,直接崩溃)。用一个例子来说明一下,我们的目标是点击一个TextView弹出“hello”信息,长按它弹出”hello world”信息。
方法的签名(signature)要和处理事件用的listener完全一样,比如对于view的onClick事件,它对应的listener的处理方法是:
public interface OnClickListener {
void onClick(View v);
}
在而长按事件是
public interface OnLongClickListener {
boolean onLongClick(View v); //注意它的返回参数是boolean
}
注意只要签名一致,所以我们创建如下响应方法:
public class MyHandler {
public void myOnClick(View view){
Toast.makeText(view.getContext(),"hello",Toast.LENGTH_SHORT).show();
}
public boolean myOnLongClick(View view){
Toast.makeText(view.getContext(),"hello world",Toast.LENGTH_SHORT).show();
return true;
}
}
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="handlers" type="com.heyy.databingexample.MyHandler"/>
data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试事件绑定"
android:onClick="@{handlers::myOnClick}"
android:onLongClick="@{handlers::myOnLongClick}"/>
LinearLayout>
layout>
同样简单点在onCreate中绑定:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
activityMainBinding.setHandlers(new MyHandler());
}
要求 android plugin 2.0+
比起Method References,这种方法多了一些特性,它是在事件发生以后才绑定的。
这种方法不再要求签名一致,而只是要求返回值一样,这样我们可以自己定制参数,用刚刚那个例子来重写一下。
这次我们在里面加一个参数
public class MyHandler {
public void myOnClick(View view, String name) {
Toast.makeText(view.getContext(), "hello " + name, Toast.LENGTH_SHORT).show();
}
}
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="handlers" type="com.heyy.databingexample.MyHandler"/>
data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试事件绑定"
android:onClick="@{(view)->handlers.myOnClick(view,"CrazyMan")}"
android:onLongClick="@{handlers::myOnLongClick}"/>
LinearLayout>
layout>
注意,传递String参数时使用了"CrazyMan",引号等需要使用HTML字符实体。
整个响应表达式是一个lambda表达式,在编译的时候数据绑定会创建一个默认响应方法,当事件触发时,默认响应方法执行这个lambda表达式。lambda表达式可以根据->分成两部分:
->左边的部分是(view) ,这里是原来listener中void onClick(View v)中的参数,这个参数必须全部写或者全部不写。比如对于:
public static interface OnCheckedChangeListener {
void onCheckedChanged(CompoundButton buttonView, boolean isChecked);
}
那么lambda左边的部分可写成
(view,checked)-> 或 ()->
简单来说,要么全写要么全不写,be alive or be die no other choice.
lambda表达式,还可以这样:
android:onClick="@{(v) > v.isVisible() ? doSomething() : void}"
简单来说,就是可以在xml执行代码,google推荐只写非常简单的逻辑(不包含任何业务逻辑),否则导致xml变复杂,会变得很难读很难管理。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
activityMainBinding.setHandlers(new MyHandler());
}