【EventBus】EventBus 源码解析 ( 事件发送 | 发布线程为 子线程 切换到 主线程 执行订阅方法的过程分析 )

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【EventBus】EventBus 源码解析 ( 事件发送 | 发布线程为 子线程 切换到 主线程 执行订阅方法的过程分析 )

文章目录

一、EventBus 中主线程支持类

二、MainThreadSupport 解析

三、MainThreadSupport 解析

四、PendingPost 链表





一、EventBus 中主线程支持类


在 EventBus.postToSubscription 方法中 , 如果当前线程是子线程 , 则调用如下方法 , 切换到主线程执行 ;


             

// 假如发布线程是子线程 , 则将事件加入队列 , 通过 Handler 切换线程执行 
                    mainThreadPoster.enqueue(subscription, event);


mainThreadPoster 是通过 mainThreadSupport.createPoster(this) 创建的 ;


注意 , 创建 mainThreadPoster 时 , 会判定当前线程是否是主线程 , 如果当前线程是主线程 , 才会创建 mainThreadPoster , 否则为空 ;


EventBus 中 mainThreadPoster 相关代码 :


public class EventBus {
    // @Nullable
    private final MainThreadSupport mainThreadSupport;
    // @Nullable
    private final Poster mainThreadPoster;
    EventBus(EventBusBuilder builder) {
        mainThreadSupport = builder.getMainThreadSupport();
        // 如果当前线程是主线程 , 才会创建 mainThreadPoster , 否则为空
        mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
    }
    private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
      // 获取该 订阅方法 的线程模式 
        switch (subscription.subscriberMethod.threadMode) {
            case MAIN:
                if (isMainThread) {
                  // 假如在主线程中 , 直接调用 
                    invokeSubscriber(subscription, event);
                } else {
                  // 假如发布线程是子线程 , 则将事件加入队列 , 通过 Handler 切换线程执行 
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
  }
  }
}





二、MainThreadSupport 解析


MainThreadSupport 是一个接口 , 在 AndroidHandlerMainThreadSupport 实现类中的 createPoster 方法中 , 创建了一个 HandlerPoster ;


package org.greenrobot.eventbus;
import android.os.Looper;
/**
 * 接口到“主”线程,可以是您喜欢的任何线程。通常在Android上使用Android的主线程。
 */
public interface MainThreadSupport {
    boolean isMainThread();
    Poster createPoster(EventBus eventBus);
    class AndroidHandlerMainThreadSupport implements MainThreadSupport {
        private final Looper looper;
        public AndroidHandlerMainThreadSupport(Looper looper) {
            this.looper = looper;
        }
        @Override
        public boolean isMainThread() {
            return looper == Looper.myLooper();
        }
        @Override
        public Poster createPoster(EventBus eventBus) {
            return new HandlerPoster(eventBus, looper, 10);
        }
    }
}






三、MainThreadSupport 解析


调用 mainThreadSupport.createPoster(this) 创建的对象就是 HandlerPoster 对象 , 其本质是一个 Handler ;


调用 void enqueue(Subscription subscription, Object event) 方法 , 将订阅者和订阅方法 , 事件对象 传入该方法 , 将 订阅者 和 事件对象 加入到 PendingPost 链表中 ;


同时调用 sendMessage(obtainMessage()) 方法 , 向 Handler 发送消息 , 执行 handleMessage 方法中的业务逻辑 ;


在 handleMessage 方法中 , PendingPost pendingPost = queue.poll() 取出链表元素 , 每个元素中封装了 订阅者 和 事件对象 , eventBus.invokeSubscriber(pendingPost); 通过反射执行订阅方法 ;



HandlerPoster 源码 :


public class HandlerPoster extends Handler implements Poster {
    private final PendingPostQueue queue;
    private final int maxMillisInsideHandleMessage;
    private final EventBus eventBus;
    private boolean handlerActive;
    protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
        super(looper);
        this.eventBus = eventBus;
        this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
        queue = new PendingPostQueue();
    }
  // 将订阅者和订阅方法 , 事件对象 传入该方法 
    public void enqueue(Subscription subscription, Object event) {
      // PendingPost 是一个链表数据结构 , 将所有的 事件对象 , 订阅者 都封装在了该链表中 ; 
      //  将 订阅者 和 事件对象 加入到 PendingPost 链表中 
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!handlerActive) {
                handlerActive = true;
                // 向 Handler 发送消息 , 执行 handleMessage 方法
                if (!sendMessage(obtainMessage())) {
                    throw new EventBusException("Could not send handler message");
                }
            }
        }
    }
  // 不断取出 PendingPost 链表中的数据 , 执行订阅方法 
    @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;
        }
    }
}





四、PendingPost 链表


PendingPost 是一个链表数据结构 , 将所有的 事件对象 , 订阅者 都封装在了该链表中 ;


final class PendingPost {
    private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();
    Object event;
    Subscription subscription;
    PendingPost next;
}
目录
相关文章
|
1月前
|
并行计算 Java 数据处理
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
150 0
|
15天前
|
安全 程序员 API
|
11天前
|
存储 设计模式 分布式计算
Java中的多线程编程:并发与并行的深度解析####
在当今软件开发领域,多线程编程已成为提升应用性能、响应速度及资源利用率的关键手段之一。本文将深入探讨Java平台上的多线程机制,从基础概念到高级应用,全面解析并发与并行编程的核心理念、实现方式及其在实际项目中的应用策略。不同于常规摘要的简洁概述,本文旨在通过详尽的技术剖析,为读者构建一个系统化的多线程知识框架,辅以生动实例,让抽象概念具体化,复杂问题简单化。 ####
|
22天前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
15 1
|
1月前
|
JavaScript 调度
Vue事件总线(EventBus)使用指南:详细解析与实战应用
Vue事件总线(EventBus)使用指南:详细解析与实战应用
57 1
|
2月前
|
缓存 Java 应用服务中间件
Java虚拟线程探究与性能解析
本文主要介绍了阿里云在Java-虚拟-线程任务中的新进展和技术细节。
|
1月前
|
存储 运维 API
源码解密协程队列和线程队列的实现原理(一)
源码解密协程队列和线程队列的实现原理(一)
35 1
|
1月前
|
存储 安全 API
源码解密协程队列和线程队列的实现原理(二)
源码解密协程队列和线程队列的实现原理(二)
33 1
|
1月前
|
安全 Java 数据库连接
Python多线程编程:竞争问题的解析与应对策略
Python多线程编程:竞争问题的解析与应对策略
22 0
|
1月前
|
安全 Java 数据库连接
Python多线程编程:竞争问题的解析与应对策略【2】
Python多线程编程:竞争问题的解析与应对策略【2】
22 0

推荐镜像

更多