前言
写一个界面的各种点击事件的时候难免会写很多id.setOnClickListener(this)
这样的代码,写的时间多了,难免会烦恼,老子为什么要写那么多重复的代码啊!!
既然不想写那么多重复代码,那么就自己来写个扩展吧。
开始
在写点击事件的时候,会让类实现View.OnClickListener
接口,然后在写控件setOnClickListener()
方法,既然每个控件都要写,不如写个扩展方法,参数是一个可变参数,类型为View
,然后在里面实现每个控件的setOnClickListener()
方法。
fun View.OnClickListener.setOnClickListener(vararg ids: View?) {
ids.filterNotNull().forEach {
it.setOnClickListener(this)
}
}
使用的时候是这样的:
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
版本,如果用最新的可以按照思路自己实现)来控制,那么就写个扩展来对应判断重复点击事件,其中里面会用到RxJava
的CompositeSubscription
来取消所有订阅。
基类
首先要在Activity
或者Fragment
的基类里面写CompositeSubscription
的取消订阅。
class BaseTestActivity : AppCompatActivity() {
protected val compositeSubscription = CompositeSubscription()
override fun onDestroy() {
compositeSubscription.clear()
super.onDestroy()
}
}
compositeSubscription
在子类用到,所以设置为protected
。
扩展
在写这个扩展的时候,分两个情况,在RecyclerView的ViewHolder里面的时候,是不需要用到CompositeSubscription
来取消订阅事件的,在Activity
或者Fragment
上面才用到的。
ViewHolder
由于不同人的封装的ViewHolder的代码不一样,这里就直接用自己项目上的代码列举出来,大家可以根据自己项目的代码自己调整,最终实现的代码是这样的:
class TestBinder : ItemBinder(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
那样的扩展方法。
实现
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上面使用,我们期望的实现是这样的:
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)
响应点击事件:
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) })
}
}
结尾
每天写那么多重复的代码,总会有不想写的时候,这也就是这篇博客产生的原因,如果大家有更好的实现方案也可以分享出来。