安卓kotlin使用callbackFlow封装控件点击事件

callbackFlow看起来方便把回调的事件封装为流,参考其他一些资料,再动手封装如下:

import android.view.View
import androidx.lifecycle.LifecycleCoroutineScope
import com.chetuan.findcar2.R
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.channels.SendChannel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

fun <E> SendChannel<E>.safeSend(value: E) = try {
    trySend(value)
} catch (e: CancellationException) {
    e.printStackTrace()
}

fun View.clickFlow(): Flow<View> {
    return callbackFlow {
        setOnClickListener {
            safeSend(it)
        }
        awaitClose { setOnClickListener(null) }
    }
}

inline fun View.click(lifecycle: LifecycleCoroutineScope, crossinline onClick: (view: View) -> Unit) {
    clickFlow().onEach {
        onClick(this)
    }.launchIn(lifecycle)
}

/**
 * 延迟第一次点击事件
 *
 * Example:
 *
 * view.clickDelayed(lifecycleScope) {
 *     showShortToast("xxx")
 * }
 */
inline fun View.clickDelayed(
    lifecycle: LifecycleCoroutineScope,
    delayMillis: Long = 500,
    crossinline onClick: (view: View) -> Unit
) {
    clickFlow().onEach {
        delay(delayMillis)
        onClick(this)
    }.launchIn(lifecycle)
}


fun getLastMillis(v: View, id: Int): Long {
    return if (v.getTag(id) != null) v.getTag(id) as Long else 0L
}

fun setLastMillis(v: View, id: Int, millis: Long) {
    v.setTag(id, millis)
}

inline fun View.clickTrigger(
    lifecycle: LifecycleCoroutineScope,
    intervalMillis: Long = 1000,
    crossinline onClick: (view: View) -> Unit
) {
    val id = R.id.tag_pos_key
    clickFlow().onEach {
        val currentMillis = System.currentTimeMillis()
        if (currentMillis - getLastMillis(this, id) < intervalMillis) {
            return@onEach
        }
        setLastMillis(this, id, currentMillis)
        onClick(this)
    }.launchIn(lifecycle)
}

在Activity/Fragment中用法如下:

binding.btnCommit.clickTrigger(lifecycleScope) {
    commit()
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值