美文网首页
自己写一个 KEventBus(三)—— Sticky Even

自己写一个 KEventBus(三)—— Sticky Even

作者: Vic_wkx | 来源:发表于2021-03-24 11:43 被阅读0次

EventBus 的运行流程一般都是:先建立 event 和 method 的订阅关系,再 post event,然后在 method 中接收 event 并处理。

但有时我们需要处理这样的情况:先 post event,然后建立 event 和 method 的订阅关系。建立时需要接收之前 post 的 event 并处理。

这样的 event 就叫做 Sticky Event(粘性事件)。

想要实现这个功能,我们需要在 post event 时,将 event 保存起来。在订阅关系建立时,如果发现这个 method 是 sticky 的,则检查是否有已存的 event,如果有,则触发一次 method。

一、新增 sticky 变量

修改 @Subscribe

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class Subscribe(val threadMode: ThreadMode = ThreadMode.MAIN, val sticky: Boolean = false)

二、在 KEventBus 中保存 Sticky 消息

KEventBus 中新增 postSticky 方法,将 Sticky 消息保存到 stickyEvents 中:

object KEventBus {
    //...

    private val stickyEvents = mutableMapOf<Class<*>, Any>()

    fun postSticky(event: Any) {
        stickyEvents[event.javaClass] = event
        post(event)
    }

    fun removeSticky(event: Class<*>) {
        stickyEvents.remove(event)
    }
}

可以看到,stickyEvents 的类型时 MutableMap<Class<*>, Any>(),这意味着如果 post 多条同一类型的 Sticky 消息,只会保留最后一条。

在 postSticky 方法中将 event 保存后,正常调用 post(event) 方法,使得当前已经订阅的 method 能够正常接收消息。

removeSticky 方法用于移除不需要的 Sticky 消息。

三、register 时处理 Sticky 消息

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 (it.getAnnotation(Subscribe::class.java)!!.sticky) {
                    if (stickyEvents[eventType] != null) {
                        it(obj, stickyEvents[eventType])
                    }
                }
            }
        }
    }
}

在 register 时,如果发现此方法是 sticky 的,则从 stickyEvents 中寻找是否有此事件类型的 Sticky 消息,如果存在,则调用一次 method。

四、测试

先 post sticky 消息:

KEventBus.postSticky("It's a sticky message")

接收方法:

@Subscribe(sticky = true)
fun onStickyEvent(message: String) {
    Log.d("~~~", message)
}

然后注册订阅关系:

KEventBus.register(this)

注册时,Log 控制台输出如下:

~~~: It's a sticky message

相关文章

网友评论

      本文标题:自己写一个 KEventBus(三)—— Sticky Even

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