我的Kotlin之旅

记一次写点击事件的扩展

2019-03-28  本文已影响4人  叫我旺仔

前言

写一个界面的各种点击事件的时候难免会写很多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版本,如果用最新的可以按照思路自己实现)来控制,那么就写个扩展来对应判断重复点击事件,其中里面会用到RxJavaCompositeSubscription来取消所有订阅。

基类

首先要在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<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那样的扩展方法。

实现

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) })
    }
}

结尾

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

上一篇下一篇

猜你喜欢

热点阅读