记一次写点击事件的扩展


前言

写一个界面的各种点击事件的时候难免会写很多id.setOnClickListener(this)这样的代码,写的时间多了,难免会烦恼,老子为什么要写那么多重复的代码啊!!

既然不想写那么多重复代码,那么就自己来写个扩展吧。

开始

在写点击事件的时候,会让类实现View.OnClickListener接口,然后在写控件setOnClickListener()方法,既然每个控件都要写,不如写个扩展方法,参数是一个可变参数,类型为View,然后在里面实现每个控件的setOnClickListener()方法。

1
2
3
4
5
6
fun View.OnClickListener.setOnClickListener(vararg ids: View?) {
ids.filterNotNull().forEach {
it.setOnClickListener(this)
}
}

使用的时候是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class TestActivity : AppCompatActivity(), View.OnClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
setOnClickListener(one, two)
}
override fun onClick(v: View) {
when (v.id) {
R.id.one -> {
}
R.id.two -> {
}
else -> {
}
}
}
}

是不是省掉了很多重复的代码。。

延伸

在写点击事件的时候,往往要判断重复点击,那么就会用到RxView(RxBinding第三方库,由于公司项目用的版本还是0.4.0版本,如果用最新的可以按照思路自己实现)来控制,那么就写个扩展来对应判断重复点击事件,其中里面会用到RxJavaCompositeSubscription来取消所有订阅。

基类

首先要在Activity或者Fragment的基类里面写CompositeSubscription的取消订阅。

1
2
3
4
5
6
7
8
class BaseTestActivity : AppCompatActivity() {
protected val compositeSubscription = CompositeSubscription()
override fun onDestroy() {
compositeSubscription.clear()
super.onDestroy()
}
}

compositeSubscription在子类用到,所以设置为protected

扩展

在写这个扩展的时候,分两个情况,在RecyclerView的ViewHolder里面的时候,是不需要用到CompositeSubscription来取消订阅事件的,在Activity或者Fragment上面才用到的。

ViewHolder

由于不同人的封装的ViewHolder的代码不一样,这里就直接用自己项目上的代码列举出来,大家可以根据自己项目的代码自己调整,最终实现的代码是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
class TestBinder : ItemBinder<TestEntity>(R.layout.item_test){
override fun onBindViewHolder(holder: ViewHolder, item: TestEntity) {
holder.run {
setOnClickThrottleFirst(one, two, three) {
when (it.id) {
R.id.one -> {}
R.id.two -> {}
else -> {}
}
}
}
}
}

由于会用到数据类的对象,所以不能用View.OnClickListener那样的扩展方法。

实现
1
2
3
4
5
6
7
8
9
10
11
fun setOnClickThrottleFirst(
vararg ids: View?,
block: (View) -> Unit
) {
ids.filterNotNull().forEach { view ->
RxView.clicks(view)
.throttleFirst(1, TimeUnit.SECONDS)
.subscribe { block(view) }
}
}

Activity或者Fragment

在Activity或者Fragment上面使用,我们期望的实现是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fun test() {
setOnClickThrottleFirst(
compositeSubscription,
one,
two,
three,
four
)
}
override fun onClick(v: View) {
when (v.id) {
R.id.one -> {}
R.id.two -> {}
R.id.three -> {}
R.id.four -> {}
else -> {}
}
}

实现

看了上面的ViewHolder的时候就会发现,这里很简单,只需要加个CompositeSubscription参数,同时将调用函数参数的那里改成,onClick(View)响应点击事件:

1
2
3
4
5
6
7
8
9
10
fun View.OnClickListener.setOnClickThrottleFirst(
compositeSubscription: CompositeSubscription,
vararg ids: View?
) {
ids.filterNotNull().forEach { view ->
compositeSubscription.add(RxView.clicks(view)
.throttleFirst(1, TimeUnit.SECONDS)
.subscribe { onClick(view) })
}
}

结尾

每天写那么多重复的代码,总会有不想写的时候,这也就是这篇博客产生的原因,如果大家有更好的实现方案也可以分享出来。