前言
寫一個(gè)界面的各種點(diǎn)擊事件的時(shí)候難免會(huì)寫很多id.setOnClickListener(this)
這樣的代碼缝裁,寫的時(shí)間多了,難免會(huì)煩惱,老子為什么要寫那么多重復(fù)的代碼按馕邸q孟弧粥航!
既然不想寫那么多重復(fù)代碼递雀,那么就自己來寫個(gè)擴(kuò)展吧。
開始
在寫點(diǎn)擊事件的時(shí)候,會(huì)讓類實(shí)現(xiàn)View.OnClickListener
接口滤奈,然后在寫控件setOnClickListener()
方法蜒程,既然每個(gè)控件都要寫伺帘,不如寫個(gè)擴(kuò)展方法伪嫁,參數(shù)是一個(gè)可變參數(shù),類型為View
帝洪,然后在里面實(shí)現(xiàn)每個(gè)控件的setOnClickListener()
方法碟狞。
fun View.OnClickListener.setOnClickListener(vararg ids: View?) {
ids.filterNotNull().forEach {
it.setOnClickListener(this)
}
}
使用的時(shí)候是這樣的:
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 -> {
}
}
}
}
是不是省掉了很多重復(fù)的代碼。脆淹。
延伸
在寫點(diǎn)擊事件的時(shí)候盖溺,往往要判斷重復(fù)點(diǎn)擊铣缠,那么就會(huì)用到RxView
(RxBinding第三方庫(kù)蝗蛙,由于公司項(xiàng)目用的版本還是0.4.0
版本捡硅,如果用最新的可以按照思路自己實(shí)現(xiàn))來控制壮韭,那么就寫個(gè)擴(kuò)展來對(duì)應(yīng)判斷重復(fù)點(diǎn)擊事件喷屋,其中里面會(huì)用到RxJava
的CompositeSubscription
來取消所有訂閱屯曹。
基類
首先要在Activity
或者Fragment
的基類里面寫CompositeSubscription
的取消訂閱。
class BaseTestActivity : AppCompatActivity() {
protected val compositeSubscription = CompositeSubscription()
override fun onDestroy() {
compositeSubscription.clear()
super.onDestroy()
}
}
compositeSubscription
在子類用到,所以設(shè)置為protected
批什。
擴(kuò)展
在寫這個(gè)擴(kuò)展的時(shí)候社搅,分兩個(gè)情況,在RecyclerView的ViewHolder里面的時(shí)候暮的,是不需要用到CompositeSubscription
來取消訂閱事件的冻辩,在Activity
或者Fragment
上面才用到的。
ViewHolder
由于不同人的封裝的ViewHolder的代碼不一樣放坏,這里就直接用自己項(xiàng)目上的代碼列舉出來,大家可以根據(jù)自己項(xiàng)目的代碼自己調(diào)整淤年,最終實(shí)現(xiàn)的代碼是這樣的:
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 -> {}
}
}
}
}
}
由于會(huì)用到數(shù)據(jù)類的對(duì)象犁享,所以不能用View.OnClickListener
那樣的擴(kuò)展方法豹休。
實(shí)現(xiàn)
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上面使用威根,我們期望的實(shí)現(xiàn)是這樣的:
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 -> {}
}
}
實(shí)現(xiàn)
看了上面的ViewHolder的時(shí)候就會(huì)發(fā)現(xiàn)敢茁,這里很簡(jiǎn)單留美,只需要加個(gè)CompositeSubscription參數(shù)谎砾,同時(shí)將調(diào)用函數(shù)參數(shù)的那里改成景图,onClick(View)
響應(yīng)點(diǎn)擊事件:
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) })
}
}
結(jié)尾
每天寫那么多重復(fù)的代碼,總會(huì)有不想寫的時(shí)候扣典,這也就是這篇博客產(chǎn)生的原因慎玖,如果大家有更好的實(shí)現(xiàn)方案也可以分享出來趁怔。