这是一个基于rxjava2实现的事件总线类,可以方便的使用关键字来发送和订阅信息。
代码
class RxBus {
companion object {
private val _instance: RxBus by lazy { RxBus() }
val instance get() = _instance
}
data class RxMsg(val action: String, val event: Any)
private val bus: FlowableProcessor by lazy { PublishProcessor.create().toSerialized() }
private val map = mutableMapOf>>()
fun post(a: String, o: T) = SerializedSubscriber(bus).onNext(RxMsg(a, o))
fun flowable(clazz: Class,
action: String,
scheduler: Scheduler = AndroidSchedulers.mainThread()): Flowable {
return bus.ofType(RxMsg::class.java).filter {
it.action == action && clazz.isInstance(it.event)
}.map { clazz.cast(it.event) }.observeOn(scheduler)
}
inline fun flowable(action: String,
scheduler: Scheduler = AndroidSchedulers.mainThread()): Flowable =
flowable(T::class.java, action, scheduler)
fun subscribe(clazz: Class,
target: Any,
action: String,
scheduler: Scheduler = AndroidSchedulers.mainThread(),
call: (T) -> Unit): Disposable =
flowable(clazz, action, scheduler).subscribe { call(it) }.also { obs ->
map.getOrPut(target, { mutableMapOf() }).getOrPut(action, { mutableListOf() }).add(obs)
}
inline fun subscribe(target: Any,
action: String,
scheduler: Scheduler = AndroidSchedulers.mainThread(),
noinline call: (T) -> Unit): Disposable =
subscribe(T::class.java, target, action, scheduler, call)
fun unsubscribe(target: Any, action: String? = null) {
map[target]?.let {
if (action != null) it.remove(action)?.onEach { it.dispose() }
else it.onEach { it.value.forEach { it.dispose() } }.clear()
if (it.isEmpty()) map.remove(target)
}
}
}
使用
- 在指定对象上按关键字订阅, 可以按指定关键字(action)和类型(String)接收数据。
RxBus.instance.subscribe(this, "action") { println(it) }
- 按关键字取消订阅
RxBus.instance.unsubscribe(this, "action")
- 取消指定对象上的全部订阅
RxBus.instance.unsubscribe(this)
- 发送消息,会自动发送指定类型数据给订阅者。
RxBus.instance.post("action", "msg")
- 也可不依赖于一个对象,这样需要手工调用 dispose() 取消订阅,或者使用RxLifecycle管理订阅。
val disposable = RxBus.instance.flowable("action").observeOn(AndroidSchedulers.mainThread()).subscribe {
println(it)
}
disposable.dispose()
示例
override fun onCreate(state: Bundle?) {
super.onCreate(state)
setContentView(R.layout.activity_main)
RxBus.instance.subscribe(this, "click") {
Toast.makeText(this, it, Toast.LENGTH_SHORT).show()
}
findViewById