claude
我仔细审查了你的事件系统实现,发现了一些问题和可以优化的地方:
🔴 严重问题
1. 泛型类型擦除导致监听器混乱
inline fun <reified T : AppEvent> on(noinline handler: (T) -> Unit): EventListener<T> {
return on(T::class.java, Consumer(handler))
}
fun <T : AppEvent> on(clazz: Class<T>, handler: Consumer<T>): EventListener<T> {
val listener = EventListener(handler)
listeners.computeIfAbsent(clazz) { CopyOnWriteArrayList() }.add(listener)
return listener
}问题: 当你监听父类事件时,子类事件不会触发监听器。
// 这个监听器永远不会被触发!
eventBus.on<AppEvent> { event ->
println("Any event: $event")
}
eventBus.emit(ServerStarted(colleen)) // 不会触发上面的监听器原因: listeners[event::class.java] 只会查找精确匹配的类型。
2. off() 方法性能问题
fun off(listener: EventListener<*>) {
listeners.values.forEach { it.remove(listener) }
}遍历所有事件类型的所有监听器,复杂度是 O(n*m)。应该记录监听器注册的事件类型。
3. 事件冒泡逻辑不完整
if (event.bubbles && !event.isPropagationStopped) {
parent?.emit(event)
}问题:
没有设置
currentTarget子App的事件会冒泡到父App,但
target始终指向子App,父App监听器可能需要知道当前处理节点
🟡 设计问题
4. data class 事件的陷阱
data class ServerStarted(override val target: Colleen) : AppEvent(target, false)问题: data class 的 equals/hashCode 只基于构造参数,不包括继承的属性:
val event1 = ServerStarted(colleen)
event1.stopPropagation()
val event2 = event1.copy()
// event2.isPropagationStopped == false! 😱5. 线程安全问题
var isPropagationStopped: Boolean = false
private set在多线程环境下,这个变量应该是 @Volatile 或使用 AtomicBoolean。
6. 异常处理过于宽泛
try {
(listener as EventListener<T>).handler.accept(event)
} catch (e: Exception) {
logger.error("Error in event listener: ${e.message}")
}吞掉所有异常可能隐藏严重bug。应该至少记录堆栈跟踪,或提供错误处理策略。
📝 改进建议
完整优化版本
sealed class AppEvent(
open val target: Colleen,
val bubbles: Boolean = true,
) {
var currentTarget: Colleen? = null
internal set
@Volatile
private var _propagationStopped: Boolean = false
val isPropagationStopped: Boolean
get() = _propagationStopped
fun stopPropagation() {
_propagationStopped = true
}
val timestamp: Long = System.currentTimeMillis()
}
// 使用普通 class 而非 data class
class ServerStarted(override val target: Colleen) : AppEvent(target, false) {
override fun toString() = "ServerStarted(target=$target)"
}
class EventListener<T : AppEvent>(
val eventType: Class<out AppEvent>, // 记录类型,优化off()
val handler: Consumer<T>,
)
class EventBus {
internal var parent: EventBus? = null
@PublishedApi
internal val listeners =
ConcurrentHashMap<Class<out AppEvent>, CopyOnWriteArrayList<EventListener<out AppEvent>>>()
inline fun <reified T : AppEvent> on(
includeSubtypes: Boolean = false,
noinline handler: (T) -> Unit
): EventListener<T> {
return on(T::class.java, includeSubtypes, Consumer(handler))
}
fun <T : AppEvent> on(
clazz: Class<T>,
includeSubtypes: Boolean = false,
handler: Consumer<T>
): EventListener<T> {
val listener = EventListener(clazz, handler)
if (includeSubtypes) {
// 如果需要监听子类型,需要特殊处理
// 这里简化:只注册到具体类型
logger.warn("includeSubtypes not fully implemented yet")
}
listeners.computeIfAbsent(clazz) { CopyOnWriteArrayList() }.add(listener)
return listener
}
fun off(listener: EventListener<*>) {
// 优化: 直接从对应类型的列表中移除
listeners[listener.eventType]?.remove(listener)
}
fun <T : AppEvent> emit(event: T) {
// 设置当前目标
event.currentTarget = event.target
val eventListeners = listeners[event::class.java]
eventListeners?.forEach { listener ->
if (event.isPropagationStopped) return@forEach
@Suppress("UNCHECKED_CAST")
try {
(listener as EventListener<T>).handler.accept(event)
} catch (e: Exception) {
// 记录完整堆栈,便于调试
logger.error("Error in event listener for ${event::class.simpleName}", e)
// 可选: 抛出包装后的异常或触发错误事件
// throw EventListenerException("Listener failed", e)
}
}
// 冒泡到父节点
if (event.bubbles && !event.isPropagationStopped && parent != null) {
// 更新 currentTarget 为父节点
val originalTarget = event.currentTarget
parent?.emit(event)
event.currentTarget = originalTarget // 恢复
}
}
}🎯 关键改进点
移除 data class: 避免
copy()导致的状态丢失添加 @Volatile: 保证线程安全
优化 off(): 从 O(n*m) 到 O(1)
完善 currentTarget: 正确处理冒泡过程
增强异常日志: 记录完整堆栈和事件类型
提供 includeSubtypes 选项: 为未来支持继承链监听预留接口
🤔 架构建议
考虑添加这些功能:
// 1. 事件优先级
class EventListener<T : AppEvent>(
val eventType: Class<out AppEvent>,
val handler: Consumer<T>,
val priority: Int = 0 // 数字越大优先级越高
)
// 2. 一次性监听器
fun <T : AppEvent> once(handler: (T) -> Unit): EventListener<T>
// 3. 异步事件发射
suspend fun <T : AppEvent> emitAsync(event: T)
// 4. 事件拦截器(可修改事件)
fun <T : AppEvent> intercept(handler: (T) -> T)你的框架目前是同步框架还是协程框架?这会影响事件系统的设计方向。