前言
事件处理是Android中最常见的功能,比如按钮的点击事件等,如果不使用数据绑定,就需要拿到这个按钮,给它设置对应的事件处理方法,但是通过数据绑定,就可以编写从视图分派的表达式处理事件。
这里主要分为2种,一种是方法引用,一种是监听器绑定。
正文
方法引用
方法引用这里要明白一件事,那就是方法签名,这个不论是C/C++函数指针还是kotlin的高阶函数我们都比较熟悉,也就是参数和返回值构成一个方法的签名。
所以在表达式中,想通过方法引用来处理事件则方法签名必须一样,否则会出错。
比如看个例子,给View设置方法引用,先看一下方法签名:
imgAppIcon.setOnClickListener(object : View.OnClickListener{
override fun onClick(v: View?) {
}
})
这个方法签名就是(View) -> null,那么就可以使用一个这个签名的方法来做引用:
fun imageClick(view: View){
Log.i(TAG, "imageClick: 图片被点击")
}
然后就可以在xml中使用了,使用方法是使用 :: 来使用方法引用:
<ImageView
android:id="@+id/imgAppIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:scaleType="fitCenter"
android:layout_marginTop="30dp"
android:src="@mipmap/common_login_logo"
android:onClick="@{viewModel::imageClick}"
/>
然而这里能成功有个很重要的前提就是onClick这个叫做事件特性名是和监听器方法的名称来确定,也就是它有个监听器的名字叫做setOnClickListener,再比如可以设置onTouch,它也有一个监听器叫做setOnToucherListener,所以也可以设置成功,从这里来看,这里还是有很大的局限性。
还有一个和下面方法的区别就是,方法引用是在数据绑定创建时就会去求值然后设置上,所以会出现编译错误,下面的监听器绑定是在事件触发时才去求值。
监听器绑定
监听器绑定是事件发生时运行的绑定表达式,这个啥意思呢?
和方法引用不同,比如点击事件onClick,当视图发生点击事件时才去求值表达式,然后进行处理。
还有一个和方法引用最大的区别就是方法应用中,必须签名完全一致也就是参数和返回值必须一样,但是在监听器绑定中没有这个要求,只需要返回值匹配即可。
直接看个例子:
<Button
android:id="@+id/btnLogin"
android:layout_width="match_parent"
android:layout_height="42dp"
android:layout_marginTop="24dp"
android:textSize="17sp"
android:background="@drawable/selector_login_btn"
android:text="@string/login"
android:textColor="@color/white"
android:onClick="@{() -> viewModel.login()}"
android:enabled="@{viewModel.enableButton}"
/>
在这个onClick中,就不是一个方法引用,因为它的签名完全不匹配,这里的意思就是当点击事件发生时,传递一个空参数给login()函数,login函数返回Unit即可,只要返回值一样即可:
fun login(){
}
当然这里也可以传递参数,也就是view。
总结
事件处理的原理非常简单,首先必须这些事件特征值要有对应的set监听器的方法,然后有2种方法来对事件进行处理,第一个就是要求签名一样的方法引用,还有就是只要求返回值一样的监听器绑定。