Android EventBus 原理

发布于 2024-12-17 07:46:24 字数 2827 浏览 3 评论 0

观察者模式

发布者即发送消息的一方(即调用 EventBus.getDefault().post(event) ​ 的一方),订阅者即接收消息的一方(即调用 EventBus.getDefault().register() ​ 的一方)

register()

  1. 找到订阅者的方法。找出传进来的订阅者的所有订阅方法,然后遍历订阅者的方法。
  2. 通过反射来获取订阅者中所有的方法,并根据方法的类型,参数和注解找到订阅方法。
  3. 订阅者的注册
private void findUsingReflectionInSingleClass(FindState findState) {
    Method[] methods;
    try {
        // 通过反射来获取订阅者中所有的方法
        methods = findState.clazz.getDeclaredMethods();
    } catch (Throwable th) {
        // 

粘性事件

普通事件是先注册,然后发送事件才能收到;而粘性事件,在发送事件之后再订阅该事件也能收到。此外,粘性事件会保存在内存中,每次进入都会去内存中查找获取最新的粘性事件,除非你手动解除注册。

调用 HandlerPoster.enqueue 入队,(HandlerPoster extends Handler)最终的数据结构是 PendingPost,单链表实现的队列

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!handlerActive) {
                handlerActive = true;
                if (!sendMessage(obtainMessage())) {
                    throw new EventBusException("Could not send handler message");
                }
            }
        }
    }

在这个 Handler 里开启无限循环接受事件:

    @Override
    public void handleMessage(Message msg) {
        boolean rescheduled = false;
        try {
            long started = SystemClock.uptimeMillis();
            while (true) {
                PendingPost pendingPost = queue.poll();
                if (pendingPost == null) {
                    synchronized (this) {
                        // Check again, this time in synchronized
                        pendingPost = queue.poll();
                        if (pendingPost == null) {
                            handlerActive = false;
                            return;
                        }
                    }
                }
                eventBus.invokeSubscriber(pendingPost);
                long timeInMethod = SystemClock.uptimeMillis() - started;
                if (timeInMethod >= maxMillisInsideHandleMessage) {
                    if (!sendMessage(obtainMessage())) {
                        throw new EventBusException("Could not send handler message");
                    }
                    rescheduled = true;
                    return;
                }
            }
        } finally {
            handlerActive = rescheduled;
        }
    }

可以看出 handleMessage 对事件链表的处理是不断循环获取链表中的 PendingPost,当链表中的事件处理完毕后退出 while 循环。或者是在规定的时间内 maxMillisInsideHandleMessage 没有将事件处理完,则继续调用 sendMessage。继而重新回调 handleMessage 方法,事件会继续执行。 这是为了避免队列过长或者事件耗时较长时,while 循环阻塞主线程造成卡顿。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

情徒

暂无简介

文章
评论
25 人气
更多

推荐作者

最终幸福

文章 0 评论 0

与酒说心事

文章 0 评论 0

┈┾☆殇

文章 0 评论 0

梦醒灬来后我

文章 0 评论 0

念﹏祤嫣

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文