美文网首页
自己写一个 KEventBus(一)——核心思想

自己写一个 KEventBus(一)——核心思想

作者: Vic_wkx | 来源:发表于2021-03-22 23:58 被阅读0次

一、注解

首先声明一个注解:

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class Subscribe

Retention 表示此注解会在运行时保留,Target 表示此注解作用于方法上。

二、KEventBus

object KEventBus {

    private val subscriptionsByEventType = mutableMapOf<Class<*>, MutableList<Pair<Any, Method>>>()

    fun register(obj: Any) {
        // Reflect to get all subscribed methods
        obj.javaClass.declaredMethods.forEach {
            if (it.isAnnotationPresent(Subscribe::class.java)) {
                if (it.parameterTypes.size == 1) {
                    val eventType = it.parameterTypes.first()
                    if (eventType !in subscriptionsByEventType) {
                        subscriptionsByEventType[eventType] = mutableListOf()
                    }
                    subscriptionsByEventType[eventType]!!.add(obj to it)
                }
            }
        }
    }

    fun unregister(obj: Any) {
        obj.javaClass.declaredMethods.forEach {
            if (it.isAnnotationPresent(Subscribe::class.java)) {
                if (it.parameterTypes.size == 1) {
                    val event = it.parameterTypes.first()
                    if (event in subscriptionsByEventType) {
                        subscriptionsByEventType[event]?.remove(obj to it)
                    }
                }
            }
        }
    }

    fun post(event: Any) {
        subscriptionsByEventType[event.javaClass]?.forEach {
            it.second.invoke(it.first, event)
        }
    }
}

EventBus 是一个典型的观察者模式,当某个 Class register 时,首先会遍历一次此 Class 中的所有方法,将带有 @Subscribe 注解的方法找到,将其注册到此方法的参数类型上。也就是生成了一个 参数类型 -> 所有观察者方法 的 Map。

当 post 消息时,找到此消息类型的所有观察者,依次调用这些观察者方法,将消息作为参数传入。

取消注册就是将对应的观察者移除。

三、使用

注册:

KEventBus.register(this)

发送消息:

KEventBus.post("I'm a string message")

接收消息:

@Subscribe
fun onStringEvent(message: String) {
    Log.d("EventBus", message)
}

取消注册:

KEventBus.unregister(this)

四、后记

本文只是讲出 EventBus 的核心思想。在实际的 EventBus 中,还做了非常多的优化。主要有:

  • 提供线程切换
  • 提供 Sticky 消息
  • 保证线程安全
  • 用注解处理器生成 index 文件来获取订阅方法,以替代反射,提高性能。

相关文章

网友评论

      本文标题:自己写一个 KEventBus(一)——核心思想

      本文链接:https://www.haomeiwen.com/subject/mctpcltx.html