throttleFirst置換Coルーチンでのクリックまたはダブルクリックを避ける
既存のRxではダブルクリック/複数回クリックを防止するためにthrottleFirstを使用している.
Coルーチンでダブルクリックを防止するにはどうすればいいですか?
Actorの使用
Coルーチンでダブルクリックを防止するにはどうすればいいですか?
Actorの使用
コアコンセプト
private fun View.onClickOnce(action: suspend (View) -> Unit) {
val event = GlobalScope.actor<View>(Dispathers.Main) {
for (event in channel)
action(event)
}
setOnClickListner {
event.offer(it)
}
}
var currentIndex = 0
fab.onClickOnce {
10.countDown(currentIndex++)
}
実際の使用方法
1.BaseOneClickActivityの作成
CoroutineScope
およびAppCompatActivity
のBaseOneClickActivity
を実装/継承する.また,今後ダブルクリックを防止する必要があるactivityはBaseOneClickActivity
の使用を継承する.abstract class BaseOneClickActivity: AppCompatActivity(). CoroutineScope {
private val job: Job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
override fun onDestroy() {
super.onDestroy()
job.cancel()
}
}
abstract class MainActivity : BaseOneClickActivity() {
launch{} // UI 스레드에서 처리
launch(Dispatchers.Default) {} // Default 스레드에서 처리
actor<Generic Type> {} // UI 스레드에서 처리
actor<Generic Type>(Dispatchers.Default) {} // Default 스레드에서 처리
}
2.onClickを作成します。
この内容はちょっと難しいですが、よく見ると…
まずfun <E> View.onClick
を見て、ここではCoroutinesSendChannelOnClickEvent
がクラスを作成して戻ります.このクラスにはconsumeEach()
関数があり、コードの最下部にはinfix関数があり、.consume()
関数があります.この関数の内部にはconsumeEach()
が使用されます.
最終的には、次の用法コードのようにコードをきれいに書くために追加された関数です!
を選択します.onClick(Dispatcher){
このDispatchで実行するアクション
}consumer{//infix関数なので、このモードを使用できます.
プライマリ・スレッドで実行されるアクション
}class CoroutinesSendChannelOnClickEvent<E>(
private val view: View, // View: click을 위한 View
private val bgBody: suspend (item: View) -> E, // background에서 실행할 내용
private val dispatcherProvider: DispatchersProviderSealed = DispatchersProvider,
private val job: Job? = null) { // Job : cancel을 위한 job 추가
fun consumeEach(uiBody: (item: E) -> Unit): CoroutinesSendChannelOnClickEvent<E> {
val clickActor = CoroutineScope(dispatcherProvider.main + (job ?: EmptyCoroutineContext)).actor<View> {
this.channel.map(context = dispatcherProvider.default, transform = bgBody).consumeEach(uiBody)
}
view.setOnClickListener { clickActor.offer(it) } // Offer 처리를 위한 CoroutineScope 생성
return this
}
}
fun <E> View.onClick(dispatcherProvider: DispatchersProviderSealed = DispatchersProvider,
job: Job? = null, bgBody: suspend (item: View) -> E): CoroutinesSendChannelOnClickEvent<E> =
CoroutinesSendChannelOnClickEvent(this, bgBody, dispatcherProvider, job)
infix fun <E> CoroutinesSendChannelOnClickEvent<E>.consume(uiBody: (item: E) -> Unit) { // 생성을 간단하게 하기 위한 function 2개
this.consumeEach(uiBody)
}
使い方は以下の通りです.fab.onClick(job = job) { // click을 처리하고, background에서 loadnetwork()
loadNetwork()
} consume {
tv_message.text = it
}
private suspend fun loadNetwork(): String { // Temp load network
delay(300)
return "currentIndex ${currentIndex++}"
}
長所
既存のRx上のThrottleFirstを使用する場合、ビューごとのクリックイベントの時間を正確に判断できないため、500 ms->などの任意の時間を指定できます.これはコードインスタンスで解決できます.
Reference
この問題について(throttleFirst置換Coルーチンでのクリックまたはダブルクリックを避ける), 我々は、より多くの情報をここで見つけました
https://velog.io/@suev72/throttleFirst-대체-Coroutine에서-다중클릭이중클릭-방지
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
private fun View.onClickOnce(action: suspend (View) -> Unit) {
val event = GlobalScope.actor<View>(Dispathers.Main) {
for (event in channel)
action(event)
}
setOnClickListner {
event.offer(it)
}
}
var currentIndex = 0
fab.onClickOnce {
10.countDown(currentIndex++)
}
abstract class BaseOneClickActivity: AppCompatActivity(). CoroutineScope {
private val job: Job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
override fun onDestroy() {
super.onDestroy()
job.cancel()
}
}
abstract class MainActivity : BaseOneClickActivity() {
launch{} // UI 스레드에서 처리
launch(Dispatchers.Default) {} // Default 스레드에서 처리
actor<Generic Type> {} // UI 스레드에서 처리
actor<Generic Type>(Dispatchers.Default) {} // Default 스레드에서 처리
}
class CoroutinesSendChannelOnClickEvent<E>(
private val view: View, // View: click을 위한 View
private val bgBody: suspend (item: View) -> E, // background에서 실행할 내용
private val dispatcherProvider: DispatchersProviderSealed = DispatchersProvider,
private val job: Job? = null) { // Job : cancel을 위한 job 추가
fun consumeEach(uiBody: (item: E) -> Unit): CoroutinesSendChannelOnClickEvent<E> {
val clickActor = CoroutineScope(dispatcherProvider.main + (job ?: EmptyCoroutineContext)).actor<View> {
this.channel.map(context = dispatcherProvider.default, transform = bgBody).consumeEach(uiBody)
}
view.setOnClickListener { clickActor.offer(it) } // Offer 처리를 위한 CoroutineScope 생성
return this
}
}
fun <E> View.onClick(dispatcherProvider: DispatchersProviderSealed = DispatchersProvider,
job: Job? = null, bgBody: suspend (item: View) -> E): CoroutinesSendChannelOnClickEvent<E> =
CoroutinesSendChannelOnClickEvent(this, bgBody, dispatcherProvider, job)
infix fun <E> CoroutinesSendChannelOnClickEvent<E>.consume(uiBody: (item: E) -> Unit) { // 생성을 간단하게 하기 위한 function 2개
this.consumeEach(uiBody)
}
fab.onClick(job = job) { // click을 처리하고, background에서 loadnetwork()
loadNetwork()
} consume {
tv_message.text = it
}
private suspend fun loadNetwork(): String { // Temp load network
delay(300)
return "currentIndex ${currentIndex++}"
}
既存のRx上のThrottleFirstを使用する場合、ビューごとのクリックイベントの時間を正確に判断できないため、500 ms->などの任意の時間を指定できます.これはコードインスタンスで解決できます.
Reference
この問題について(throttleFirst置換Coルーチンでのクリックまたはダブルクリックを避ける), 我々は、より多くの情報をここで見つけました https://velog.io/@suev72/throttleFirst-대체-Coroutine에서-다중클릭이중클릭-방지テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol