Rxを使用せず、Flowを使用して複数回のクリックを防止
🤔 悩みの始まり
既存のRxJavaのコードをFlowで置き換えるときに遭遇するブロックは
throttleFirst()
である.複数回クリックしないようにするには、RxJavaのthrottleFirst()
演算子が必要です.Flowでは、この機能の演算子はサポートされていません.この演算子は、しばらくの間、最初の値のみを発行し、残りの値は無視されます.この演算子を直接実装することにした.🆖 既存のRxJavaを使用したマルチタッチコード
private fun View.setRxBindingClicks() {
this.clicks()
.throttleFirst(1000, TimeUnit.MILLISECONDS)
.subscribe { onClick(id) }
.addTo(disposeBag)
}
private fun onClick(id: Int) {
when (id) {
R.id.______ -> clickEvent()
}
}
clicks()
: RxBinding. 必要なRx演算子を使用するには、クリックイベントを観察可能な形式に変換します.throttleFirst(1000, TimeUnit.MILLISECONDS)
:Rx演算子.期間内に発生した最初のイベントを無視し、残りのイベントを無視します.🆕 Rx → Flow
演算子のカスタマイズ
// FlowExtensions.kt
// 클릭 이벤트를 flow로 변환
fun View.clicks(): Flow<Unit> = callbackFlow {
setOnClickListener {
this.trySend(Unit)
}
awaitClose { setOnClickListener(null) }
}
// 마지막 발행 시간과 현재 시간 비교해서 이벤트 발행, 나머지는 무시.
fun <T> Flow<T>.throttleFirst(windowDuration: Long): Flow<T> = flow {
var lastEmissionTime = 0L
collect { upstream ->
val currentTime = System.currentTimeMillis()
if (currentTime - lastEmissionTime > windowDuration) {
lastEmissionTime = currentTime
emit(upstream)
}
}
}
▼▼▼▼▼▼▼4▼▼▼▼▼▼▼▼▼▼▼▼▼4▼▼▼▼debounce
-特定のmsに新しいテキストが入力されていない場合はsearch()が呼び出されます.活用する
// ViewExtensions.kt
fun View.setClickEvent(
uiScope: CoroutineScope,
windowDuration: Long = THROTTLE_DURATION,
onClick: () -> Unit,
) {
clicks()
.throttleFirst(windowDuration)
.onEach { onClick.invoke() }
.launchIn(uiScope)
}
// ____Activity.kt
button.setClickEvent(lifecycleScope) {
Log.i("[TAG]", "click - ${System.currentTimeMillis()}")
}
🔗 リファレンス
https://github.com/Kotlin/kotlinx.coroutines/issues/1446
From RxJava to Kotlin Flow: Throttling
Reference
この問題について(Rxを使用せず、Flowを使用して複数回のクリックを防止), 我々は、より多くの情報をここで見つけました https://velog.io/@minji_jeong/Rx-말고-Flow로-다중클릭-방지하기-throttleFirstテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol