前言
寫一個界面的各種點擊事件的時候難免會寫很多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<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) })
}
}
結尾
每天寫那么多重復的代碼,總會有不想寫的時候,這也就是這篇博客產生的原因,如果大家有更好的實現方案也可以分享出來。