Kotlin EventBus 触发了两次
Kotlin EventBus triggered twice
我在 kotlin 中将此代码用于 eventBus,但它触发了两次。我不知道为什么会这样
object EventBus {
val bus: BroadcastChannel<Any> = BroadcastChannel<Any>(1)
private val parentJob = Job()
private val coroutineContext: CoroutineContext
get() = parentJob + Dispatchers.Default
private val scope = CoroutineScope(coroutineContext)
fun send(o: Any) {
scope.launch {
bus.send(o)
}
}
inline fun <reified T> asChannel(): ReceiveChannel<T> {
return bus.openSubscription().filter { it is T }.map { it as T }
}
}
并这样使用
EventBus.send(NetEvent(false))
听如下(此代码运行两次)
var subscription = EventBus.asChannel<NetEvent>()
var s = scope.launch {
subscription.consumeEach { event ->
Timber.i("NetEvent ${event.isConected}")
currentNet = event.isConected
}
}
我更喜欢MutableSharedFlow:
class EventBus {
private val events = MutableSharedFlow<Any>()
suspend fun dispatch(event: Any) {
events.emit(event)
}
suspend fun on(coroutineScope: CoroutineScope, handler: suspend (Any) -> Unit) =
coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
events.asSharedFlow().collect { event -> handler(event) }
}
}
class EventBusTest {
@Test
fun testEventBus() {
val events = ConcurrentLinkedDeque<String>()
runBlocking {
val eventBus = EventBus()
val job1 = eventBus.on(this) { events.add("1: $it") }
eventBus.dispatch("a")
val job2 = eventBus.on(this) { events.add("2: $it") }
eventBus.dispatch("b")
job1.cancelAndJoin()
eventBus.dispatch("c")
job2.cancelAndJoin()
}
assertEquals(listOf("1: a", "1: b", "2: b", "2: c"), events.toList())
}
}
我在 kotlin 中将此代码用于 eventBus,但它触发了两次。我不知道为什么会这样
object EventBus {
val bus: BroadcastChannel<Any> = BroadcastChannel<Any>(1)
private val parentJob = Job()
private val coroutineContext: CoroutineContext
get() = parentJob + Dispatchers.Default
private val scope = CoroutineScope(coroutineContext)
fun send(o: Any) {
scope.launch {
bus.send(o)
}
}
inline fun <reified T> asChannel(): ReceiveChannel<T> {
return bus.openSubscription().filter { it is T }.map { it as T }
}
}
并这样使用
EventBus.send(NetEvent(false))
听如下(此代码运行两次)
var subscription = EventBus.asChannel<NetEvent>()
var s = scope.launch {
subscription.consumeEach { event ->
Timber.i("NetEvent ${event.isConected}")
currentNet = event.isConected
}
}
我更喜欢MutableSharedFlow:
class EventBus {
private val events = MutableSharedFlow<Any>()
suspend fun dispatch(event: Any) {
events.emit(event)
}
suspend fun on(coroutineScope: CoroutineScope, handler: suspend (Any) -> Unit) =
coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
events.asSharedFlow().collect { event -> handler(event) }
}
}
class EventBusTest {
@Test
fun testEventBus() {
val events = ConcurrentLinkedDeque<String>()
runBlocking {
val eventBus = EventBus()
val job1 = eventBus.on(this) { events.add("1: $it") }
eventBus.dispatch("a")
val job2 = eventBus.on(this) { events.add("2: $it") }
eventBus.dispatch("b")
job1.cancelAndJoin()
eventBus.dispatch("c")
job2.cancelAndJoin()
}
assertEquals(listOf("1: a", "1: b", "2: b", "2: c"), events.toList())
}
}