EventBus → SharedFlow
老写法(Java + EventBus)
java
// 发送事件
EventBus.getDefault().post(new LoginEvent(userId));
// 接收事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onLoginEvent(LoginEvent event) {
updateUI(event.getUserId());
}
// 注册/解注册
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
问题在哪里
EventBus 通过反射查找 @Subscribe 注解方法,性能损耗虽不大但存在。事件的发送方和接收方之间完全无约束,编译期不检查事件类型。忘调 register/unregister 是常见 bug 来源。全局事件满天飞,难以追踪事件的流向。
新写法(Kotlin + SharedFlow)
kotlin
// 单例事件总线
object EventBus {
private val _events = MutableSharedFlow<Any>(replay = 0,
extraBufferCapacity = 64)
val events: SharedFlow<Any> = _events
suspend fun post(event: Any) { _events.emit(event) }
}
// 发送
viewModelScope.launch { EventBus.post(LoginEvent(userId)) }
// 接收
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
EventBus.events.collect { event ->
when (event) {
is LoginEvent -> updateUI(event.userId)
}
}
}
}
一句话注意
SharedFlow 替代 EventBus 的最大好处是类型安全------when (event) 配合 sealed class 定义事件,IDE 会提示所有可能的事件类型,不会遗漏。而且不需要 register/unregister,协程取消就自动停止接收。
extraBufferCapacity = 64 是为了没有消费者时也能缓存事件(类似 EventBus 的 sticky)。如果不需要 sticky,设 replay = 0, extraBufferCapacity = 0 并在 emit 时检查是否有订阅者。
Java Android 老项目迁移系列,持续更新中。