EventBus 源码解析

EventBus 源码解析

EventBus是一个性能高效的基于观察者模式的事件发布与订阅框架.借助EventBus,我们只需几行代码便能实现组件之间、线程之间的通信

先说明一下EventBus中三个重要的角色:PublisherEventSubscriber. Event:事件,它可以是任意类型,EventBus会根据事件的类型进行全局发送 Pushlisher:事件的发布者,它可以在任意线程中发布事件。在使用时通常调用EventBus.getDefault()方法获取一个EventBus对象,再通过链 式编程调用post()方法进行事件发送 SubScriber:事件接收者 在EventBus3.0之前,使用时必须以OnEvent开头的几种接收方法来接收事件。这些方法分别为:onEventonEventMainThreadonEventBackgroundThreadonEventAsync,但是在3.0之后处理方法可以自定义,但是要以注解@subscribe进行标示, 同时指定线程模型,线程模型默认为POSTING的方式。 Tips:本文分析的源码版本为EventBus:3.2.0

简单用法

在具体的进行源码分析前,我们回顾一下EventBus的使用流程:

java 复制代码
// 1.注册
EventBus.getDefault().register(this);
// 2.准备订阅方法
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(SayHelloEvent event) {
String message = event.getMessage();
...
}
// 3.发布事件
EventBus.getDefault().post(new SayHelloEvent("Hello,EventBus!!!"));
//4.反注册
EventBus.getDefault().unregister(this);

事件订阅发布的流程分析

我们就从用法入手,逐步分析EventBus事件发布订阅的流程.

EventBus.getDefault()创建EventBus对象

EventBus使用的过程中,不管是注册、解注册或者是发送事件都会用到这个方法,所以我们首先看一下这个方法中都是做了什么。

java 复制代码
public class EventBus{
    
    /** Log tag, apps may override it. */
	public static String TAG = "EventBus";
    
	static volatile EventBus defaultInstance;
    
	private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
	private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
    
	private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
	private final Map<Object, List<Class<?>>> typesBySubscriber;
	private final Map<Class<?>, Object> stickyEvents;
    
	private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
		@Override
			protected PostingThreadState initialValue() {
			return new PostingThreadState();
		}
	};
    
    ......
    ......
    /** Convenience singleton for apps using a process-wide EventBus instance. */
	// 单例,double check
	public static EventBus getDefault() {
			EventBus instance = defaultInstance;
			if (instance == null) {
				synchronized (EventBus.class) {
				instance = EventBus.defaultInstance;
				if (instance == null) {
					instance = EventBus.defaultInstance = new EventBus();
				}
			}
		}
		return instance;
	}
    
    public EventBus() {
		this(DEFAULT_BUILDER);
	}
    
    // eventBus的具体构建通过bulier模式完成
	EventBus(EventBusBuilder builder) {
		logger = builder.getLogger();
		//这个集合可以根据事件类型获取订阅者
		//key:事件类型class,value:CopyOnWriteArrayList<Subscription>订阅该事件的订阅者集合
		subscriptionsByEventType = new HashMap<>();
		//订阅者所订阅的事件集合
		//key:订阅者,value:List<Class<?> 该订阅者订阅的事件类型集合
		typesBySubscriber = new HashMap<>();
		//粘性事件集合
		//key:事件Class对象,value:事件对象
		stickyEvents = new ConcurrentHashMap<>();
		// 是否支持Android mainThread
		mainThreadSupport = builder.getMainThreadSupport();
		// Android mainThread 事件发送者
		mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
		// 后台线程事件发送者
		backgroundPoster = new BackgroundPoster(this);
		// 异步线程事件发送者
		asyncPoster = new AsyncPoster(this);
		indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() :0;
		// 订阅者订阅事件查找者
		subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
		builder.strictMethodVerification, builder.ignoreGeneratedIndex);
		......
		......
		// private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
		executorService = builder.executorService;
	}  
}

EventBus通过EventBusBuilder来初始化EventBus对象,通过单例模式对外公开这个实例. subscriptionsByEventTypetypesBySubScriberstickEventssubcriberMethodFinder几个属性比较重要,后续分析中会经常提到,先有个印象.

Tips: 我们可以通过EventBusBuilder来自定义配置一个EventBus对象实例.

register(Object subscriber)

创建EventBus对象之后需要将事件订阅者在EventBus中进行注册。

JAVA 复制代码
public void register(Object subscriber) {
		Class<?> subscriberClass = subscriber.getClass();
		// 解析subscriber类中@Subscribe标记的方法,返回一个List<SubscriberMethod>
		List<SubscriberMethod> subscriberMethods =
		subscriberMethodFinder.findSubscriberMethods(subscriberClass);
		synchronized (this) {
		// 遍历集合注册事件的subscriber;
		for (SubscriberMethod subscriberMethod : subscriberMethods) {
				subscribe(subscriber,subscriberMethod);
			}
		}
}

register()方法主要做了两件事情:

  • 解析subscriber对象中被@Subscribe标记的方法
  • 注册事件的Subscriber

subscriberMethodFinder.findSubscriberMethods(subscriberClass)完成了@Subscribe标记方法的解析,此步骤的具体实现不影响我们 分析事件的发布流程(后面会分析具体流程),先看看解析返回的数据

@Subscribe

java 复制代码
@Documented
@Retention(RetentionPolicy.RUNTIME) // @Subscribe注解在运行时依然存在
@Target({ElementType.METHOD})
public @interface Subscribe {
	// 事件订阅执行时的线程类型;
	ThreadMode threadMode() default ThreadMode.POSTING;
	// 是否是粘性事件
	boolean sticky() default false;
	//事件被执行的优先级,优先级越高,越早执行
	int priority() default 0;
}

SubscriberMethod.java

java 复制代码
public class SubscriberMethod {
    
	final Method method; // @Subscribe标记的方法的method
	final ThreadMode threadMode; // 线程类型
	final Class<?> eventType; // 方法参数的calss,事件的Class对象
	final int priority; //优先级
	final boolean sticky; //是否是粘性;
	/** Used for efficient comparison */
	String methodString;
	public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
		this.method = method;
		this.threadMode = threadMode;
		this.eventType = eventType;
		this.priority = priority;
		this.sticky = sticky;
	}
	...
	...
}

List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass) 完成@Subscribe注解解析,返回了解析结果 , SubscriberMethod记录了@Subscribe标记的method对象和@Subscribe的值。接着注册事件的Subscriber。

java 复制代码
		// 遍历集合注册事件的subscriber;
		for (SubscriberMethod subscriberMethod : subscriberMethods) {
				subscribe(subscriber,subscriberMethod);
			}
		}

subscribe(Object subscriber, SubscriberMethod subscriberMethod)

java 复制代码
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    //step1:
	// 获取当前观察的事件类型
	Class<?> eventType = subscriberMethod.eventType;
	// 封装成一个Subscription对象
	Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
	//通过事件类型获取该事件的订阅者集合;
	CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
	if (subscriptions == null) {
		subscriptions = new CopyOnWriteArrayList<>();
		subscriptionsByEventType.put(eventType, subscriptions);
	} else {
		if (subscriptions.contains(newSubscription)) {
			throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType);
		}
	}
	int size = subscriptions.size();
	// 按照priority的高低进行排序,将数据保存到EventBus的subscriptionsByEventType属性里面
	for (int i = 0; i <= size; i++) {
	if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
		subscriptions.add(i, newSubscription);
			break;
		}
	}
    //step2:
	// 记录注册对象观察的事件类型,反注册时会用到;
	List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
	if (subscribedEvents == null) {
		subscribedEvents = new ArrayList<>();
		typesBySubscriber.put(subscriber, subscribedEvents);
	}
	subscribedEvents.add(eventType);
	// 方法被标记为接收stick,后面会分析stick事件
	if (subscriberMethod.sticky) {
		...
		...
	}
}

先看step1干了什么?

subscribersubscriberMethod被包装成了Subscription , 为啥不直接用SubscriberMethod ? 看看Subscription里面有啥

Subscription.java

java 复制代码
final class Subscription {
	final Object subscriber; //@subscribe注解标记方法的持有对象
	final SubscriberMethod subscriberMethod; //@Subscribe标记的方法解析后的数据
	volatile boolean active;
	Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
		this.subscriber = subscriber;
		this.subscriberMethod = subscriberMethod;
		active = true;
	}
	...
	...
}

联想到Method的invoke()方法

java 复制代码
// obj:方法的持有者的实例
// args:方法参数的实例
Object invoke(Object obj,Object...args)

obj对应subscriber , method对象本身均保存在subscriberMethod 中,如果再获取args,订阅方法执行的数据就都有了,接着看往下看:

java 复制代码
	Class<?> eventType = subscriberMethod.eventType;
	// 封装成一个Subscription对象
	Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    //获取该事件类型的Subscription集合,如果没有,就创建一个新的list放进去
	CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
	if (subscriptions == null) {
		subscriptions = new CopyOnWriteArrayList<>();
		subscriptionsByEventType.put(eventType, subscriptions);
	} else {
		if (subscriptions.contains(newSubscription)) {
			throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType);
		}
	}
	int size = subscriptions.size();
	// 按照priority的高低进行排序,将Subscription数据保存进去
	for (int i = 0; i <= size; i++) {
	if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
		subscriptions.add(i, newSubscription);
			break;
		}
	}

ok , subscriptionsByEventType里面保存了事件Class --- List<Subscription>的映射关系

画张图示意一下:

接着看step2做了什么

java 复制代码
    //获取subscriber观测事件类型的集合
	List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
	if (subscribedEvents == null) {
		subscribedEvents = new ArrayList<>();
		typesBySubscriber.put(subscriber, subscribedEvents);
	}
	subscribedEvents.add(eventType);

与上面一样,subscribedEvents里面保存了订阅者subscriber --- List<事件Class>的集合映射

总结一下,register(Object subscriber)执行完成后

  • subscriber的注解数据保存到了EventBus对象的subscriptionsByEventType属性里面,通过Event的calss, 可以获取对应的Subscription , Subscription里面保存了@Subscriber标记的method执行需要的数据
  • subscriber订阅的事件类型 保存到了EventBus对象的subscribedEvents里面 , subscribedEvents里面保存了subscriber订阅的事件Class集合

post(Object event)

java 复制代码
/** Posts the given event to the event bus. */
public void post(Object event) {
	//因为可以在不同的线程中执行post方法,为了避免事件同步等操作,为不同的线程提供事件执行的环境
	//ThreadLocal原理;
	PostingThreadState postingState = currentPostingThreadState.get();
	// 事件被触发前缓存到这里;
	List<Object> eventQueue = postingState.eventQueue;
	eventQueue.add(event);
	if (!postingState.isPosting) {
		postingState.isMainThread = isMainThread();
		postingState.isPosting = true;
		...
		//触发事件
		postSingleEvent(eventQueue.remove(0), postingState);
		...
	}
}

PostingThreadState提供事件分发的执行环境,接着看postSingleEvent(eventQueue.remove(0), postingState)

java 复制代码
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
	Class<?> eventClass = event.getClass();
	boolean subscriptionFound = false;
	//事件是否支持继承结构?
	//比如有两个Event a 和 Event b , a extends b
	// 我们post event a ,由于a也可以看作一个b对象,所以也需要触发 event b;
	if (eventInheritance) {
		// 查找事件calss所有的superClass和interface,将其作为潜在的事件类型;
		List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
		int countTypes = eventTypes.size();
		for (int h = 0; h < countTypes; h++) {
			Class<?> clazz = eventTypes.get(h);
			//遍历集合发送单个事件
			subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
		}
	} else {
		//发送单个事件
		subscriptionFound = postSingleEventForEventType(event,postingState, eventClass);
	}
	if (!subscriptionFound) {
		// post(new NoSubscriberEvent(this, event));
		...
		...
	}
}

接着看postSingleEventForEventType(event, postingState, clazz);

java 复制代码
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
	CopyOnWriteArrayList<Subscription> subscriptions;
	synchronized (this) {	
		//通过subscriptionsByEventType获取事件的Subscribers;
		subscriptions = subscriptionsByEventType.get(eventClass);
	}
	// 遍历执行订阅,由于register的时候根据priority排过顺序,proprity最大的会被先执行;
	if (subscriptions != null && !subscriptions.isEmpty()) {
			for (Subscription subscription : subscriptions) {
					postingState.event = event;
					postingState.subscription = subscription;
					...
					//触发Subscriber的onEvent
					postToSubscription(subscription, event, postingState.isMainThread);
					...
				}
		return true;
	}
	return false;
}

通过事件的class 找到事件的订阅者subscriptions , 按照顺序依次执行订阅方法 , 说好的Eventbus切换线程呢?,接着跟

java 复制代码
private void postToSubscription(Subscription subscription, Object event,boolean isMainThread){
    
    // 根据threadMode,切换不同的线程或直接执行
    switch (subscription.subscriberMethod.threadMode) {
            case POSTING:
				// 直接执行订阅;
				invokeSubscriber(subscription, event);
				break;
			case MAIN:
            	if (isMainThread) {
					// 当前线程就是主线程,直接执行订阅;
					invokeSubscriber(subscription, event);
				}else{
                    //添加到mainThreadPoster的队列中去,在主线程中调用响应方法
                     mainThreadPoster.enqueue(subscription, event);
                }
            	break;
            case MAIN_ORDERED:
            	if (mainThreadPoster != null) {
                    // 主线程优先模式
                    mainThreadPoster.enqueue(subscription, event);
                }else{
                    //如果不是主线程就在当前线程中进行执行订阅
                    invokeSubscriber(subscription, event);
                }
            	break;
        	case BACKGROUND:
            	if (isMainThread){
                    // 如果是主线程,进入backgroundPoster队列中等待被执行;
                    backgroundPoster.enqueue(subscription, event);
                }else{
                    //直接执行订阅;
                    invokeSubscriber(subscription, event);
                }
            	break;
            case ASYNC:
            	//不管是不是在主线程中,都会在子线程中调用响应方法
				asyncPoster.enqueue(subscription, event);
            	break;
        	default:
            	throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
            
    }
}

// 通过反射的形式,执行对应方法,完成订阅;
void invokeSubscriber(Subscription subscription, Object event) {
	try {
		subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
	} catch (InvocationTargetException e) {
		handleSubscriberException(subscription, event, e.getCause());
	} catch (IllegalAccessException e) {
		throw new IllegalStateException("Unexpected exception", e);
	}
}

事件订阅执线程的切换分五种模式

  • POSTING :当前线程直接执行

  • MAIN : Android 主线程执行

  • MAIN_ORDERED: 如果支持主线程执行那么让主线程执行,如果不支持主线程,直接在当前线程执行

  • BACKGROUND : 如果在主线程,切换到后台线程执行,不是主线程,直接执行

  • ASYNC:另开线程执行

Event是如何切换线程的

Event切换线程执行是通过对应的Poster来实现的,下面就具体分析一下不同类型的poster

Poster.java
java 复制代码
// 定义了事件进入队列,事件的具体执行由其子类完成;
interface Poster {
	/**
	* Enqueue an event to be posted for a particular subscription.
	*
	* @param subscription Subscription which will receive the event.
	* @param event Event that will be posted to subscribers.
	*/
	void enqueue(Subscription subscription, Object event);
}

Main线程的HandlerPoster

mainThreadPoster的实例是通过mainThreadSupport.createPoster(this)来创建的,最终返回的是HandlderPoster的一个实例

java 复制代码
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.obtainPendingPost(subscription, event);
		synchronized (this) {
			//放入队列中;
			queue.enqueue(pendingPost);
			if (!handlerActive) {
				handlerActive = true;
				// 发送一个事件的执行命令
				if (!sendMessage(obtainMessage())) {
					throw new EventBusException("Could not send handler message");
				}
			}
		}
	}
    
    @Override
    public void handleMessage(Message msg) {
        boolean rescheduled = false;
        try{
            long started = SystemClock.uptimeMillis();
            while(true){
                //从队列中取出数据;
                PendingPost pendingPost = queue.poll();
                if (pendingPost == null){
                    // Check again, this time in synchronized
                    synchronized (this){
                       pendingPost = queue.poll(); 
                        if (pendingPost == null){
                            handlerActive = false;
                            return;
                        }
                    }
                    // 切换到主线程执行;
					eventBus.invokeSubscriber(pendingPost);
                }
            }
        }finally{
            handlerActive = rescheduled;
        }
    }
    
    void invokeSubscriber(PendingPost pendingPost){
        Object event = pendingPost.event;
        Subscription subscription = pendingPost.subscription;
        PendingPost.releasePendingPost(pendingPost);
        if (subscription.active){
            // 实际还是调用的invokeSubscriber
            invokeSubscriber(subscription, event);
        }
    }
      
}
  • HandlerPoster通过handdler的原理,将事件执行切换到main线程。

ASYNC 额外开启异步线程 AsyncPoster.java

java 复制代码
class AsyncPoster implements Runnable, Poster {
    
    private final PendingPostQueue queue;
    private final EventBus eventBus;
    
    AsyncPoster(EventBus eventBus){
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }
    
    public void enqueue(Subscription subscription, Object event){
        // 数据包装;
		PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        // 数据入队列;
        queue.enqueue(pendingPost);
        // 执行run方法,开新的线程;
        eventBus.getExecutorService().execute(this);
    }
    
    @Override
	public void run() {
		// 获取订阅数据;
		PendingPost pendingPost = queue.poll();
		if(pendingPost == null) {
			throw new IllegalStateException("No pending post available");
		}
		// 事件具体执行位置,实现是在eventBus.getExecutorService()指定的线程
		eventBus.invokeSubscriber(pendingPost);
	}
}
  • asyncPoster执行事件在eventBus.getExecutorService()的线程池的线程里面,每次发布事件都会在新线程里面执行
JAVA 复制代码
// EventBus的默认线程池,每次执行runnable都是新开线程;
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();

/*
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
}*/

BACKGROUND 后台线程执行事件

java 复制代码
final class BackgroundPoster implements Runnable, Poster{
    
    private final PendingPostQueue queue;
	private final EventBus eventBus;
    private volatile boolean executorRunning;
    
    BackgroundPoster(EventBus eventBus) {
		this.eventBus = eventBus;
		queue = new PendingPostQueue();
	}
	// 事件进入backgroundPoster后是按照顺序执行的,每一批执行事件都是在同一个线程里面,下一批次事件执行会开启一个新的线程;
    public void enqueue(Subscription subscription, Object event){
        // 数据包装;
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
           // 数据入队列 
           queue.enqueue(pendingPost);
           // 数据并不是马上放入线程里面等待执行,而是在当前批次里面依次执行;
           // 每次执行时只开一条线程;
           if (!executorRunning){
               executorRunning = true;
               eventBus.getExecutorService().execute(this);
           } 
        }
    }
    
    @Override
	public void run() {
        try{
            //循环,每次执行都是将队列里面的事件全部执行完后才退出线程;
            while(true){
                PendingPost pendingPost = queue.poll(1000);
                if (pendingPost == null) {
                    synchronized (this) {
                        pendingPost = queue.poll();
                        if (pendingPost == null){
                            executorRunning = false;
                            return;
                        }
                    }
                }
                // 事件执行;
                eventBus.invokeSubscriber(pendingPost);
            }
        }catch(){
            eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);
        }finally{
            executorRunning = false;
        }
    }
    
}
  • backgroundPoster执行事件也是在eventBus.getExecutorService()的线程池的线程里面,直到当前队列里面事件执行完成之前,不会开启新的 线程来执行事件,事件的执行过程是串联起来的.也可以理解为事件是分批次来执行的,不同批次会开不同的线程执行,同一批次里面的事件在同 一个线程里面按照串联顺序依次执行.

unregister(Object subscriber)

EventBus.getDefault()返回的是一个单例对象,保存在subscriptionsByEventType中的Subscribers不使用时需要清除避免内存泄漏.

java 复制代码
public synchronized void unregister(Object subscriber) {
	// 获取订阅对象拥有的所有事件类型,register时保存过subscriber观察的事件种类;
	List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
	if (subscribedTypes != null) {
		for (Class<?> eventType : subscribedTypes) {
			// 注销每种事件类型对应的Subscription;
			unsubscribeByEventType(subscriber, eventType);
		}
		typesBySubscriber.remove(subscriber);
	} else {
		...
	}
}

// 注销每种事件类型对应的Subscription,防止内存泄漏;
private void unsubscribeByEventType(Object subscriber, Class<?> eventType){
    List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    if (subscriptions != null){
        int size = subscriptions.size();
        for (int i = 0; i < size; i++){
            Subscription subscription = subscriptions.get(i);
            if (subscription.subscriber == subscriber){
                subscription.active = false;
                subscriptions.remove(i);
                i--;
				size--;
            }
        }
    }
}

OK , EventBus的主体流程就到处结束了

补充

Stick事件

stick事件与一般事件的区别在于stick事件的执行时机

java 复制代码
public void postSticky(Object event){
    synchronized (stickyEvents){
       // 将事件存入stickyEvents容器内
       stickyEvents.put(event.getClass(), event);
    }
    // 此时只是当作普通事件被post;
    post(event);
}

// 移除stickevnet;
public <T> T removeStickyEvent(Class<T> eventType){
    synchronized (stickyEvents){
        return eventType.cast(stickyEvents.remove(eventType));
    }
}

stick事件是在register时触发的,看一下register方法内部的subscribe方法:

java 复制代码
subscribe(Object subscriber, SubscriberMethod subscriberMethod){
    Class<?> eventType = subscriberMethod.eventType;
	Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
	......
	......
	if (subscriberMethod.sticky){
    // 默认eventInheritance = true;
    	if (eventInheritance){
        	// 遍历stickEvents容器,postStick的stick事件会被存进去, key是事件的calss对象,value是event实例
       		 Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet(); 
        	for (Map.Entry<Class<?>, Object> entry : entries){
           		 Class<?> candidateEventType = entry.getKey();
            	// a.isAssignableFrom(b),a为b的父类或者接口|a与b是同一个类或者接口;
            	if (eventType.isAssignableFrom(candidateEventType)){
                    Object stickyEvent = entry.getValue();
                    // 触发stickEvent,注意post的event对象是之前存储在stickyEvents中的对象;
                    checkPostStickyEventToSubscription(newSubscription,stickyEvent);
            	}
        	}
    	}else{
            Object stickyEvent = stickyEvents.get(eventType);
            checkPostStickyEventToSubscription(newSubscription, stickyEvent);
        }
	}    
}

// 执行事件订阅,与上面post方法殊途同归
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent){
    if (stickyEvent != null) {
		postToSubscription(newSubscription, stickyEvent, isMainThread());
	}
}

@Subscribe注解的解析的过程

最后补充一下@Subscribe的解析过程

SubscriberMethodFinder.java
java 复制代码
class SubscriberMethodFinder{
    
    private static final int BRIDGE = 0x40;
    private static final int SYNTHETIC = 0x1000;
    private static final int MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;
    private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
    
    private List<SubscriberInfoIndex> subscriberInfoIndexes;
    private final boolean strictMethodVerification; // 是否开启严格验证
    private final boolean ignoreGeneratedIndex;
    private static final int POOL_SIZE = 4;
    private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];
    
    SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean strictMethodVerification,
			boolean ignoreGeneratedIndex){
        this.subscriberInfoIndexes = subscriberInfoIndexes;
        this.strictMethodVerification = strictMethodVerification; // 默认false;
        this.ignoreGeneratedIndex = ignoreGeneratedIndex; // 默认false;
    }
    
    ......
    ......
        
    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass){
        // 有缓存,直接从缓存中拿
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
			return subscriberMethods;
		}
        if (ignoreGeneratedIndex) {
            // 通过反射来解析数据;
            subscriberMethods = findUsingReflection(subscriberClass);
        }else{
            // 通过apt来获取解析数据;
            subscriberMethods = findUsingInfo(subscriberClass);
        }
        // 如果一个subscribe注解方法都没有找到,throw exception(),是不是见过这个异常
        if (subscriberMethods.isEmpty()) {
			throw new EventBusException("Subscriber " + subscriberClass
			+ " and its super classes have no public methods with the @Subscribe annotation");
		}else {
            // 记录一下,第二次使用时直接使用缓存;
            METHOD_CACHE.put(subscriberClass, subscriberMethods);
            return subscriberMethods;
        }  
    }
    
    //  通过反射来解析@Subscribe,数据的解析实际上放到了FindState类里面处理
    private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
        FindState findState = prepareFindState(); // 享元模式
        findState.initForSubscriber(subscriberClass);
        // 切换到父类class,这样父类calss里面的@subscribe注解的方法也可以解析到
        while (findState.clazz != null) {
            findUsingReflectionInSingleClass(findState);
            findState.moveToSuperclass();
        }
        return getMethodsAndRelease(findState);
    }
    
    private FindState prepareFindState() {
        synchronized (FIND_STATE_POOL) {
            for (int i = 0; i < POOL_SIZE; i++) {
                FindState state = FIND_STATE_POOL[i];
                if (state != null) {
                    FIND_STATE_POOL[i] = null;
                    return state;
                }
            }
        }
        return new FindState();
    }
     
    // 解析@Subscribe注解的辅助类
    static class FindState{
        
        final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
		final Map<Class, Object> anyMethodByEventType = new HashMap<>();
		final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
		final StringBuilder methodKeyBuilder = new StringBuilder(128);
        
        ......
        ......
        
       	 	//把当前class设置为父类class,过滤系统层面calss,防止无限制的解析
        	void moveToSuperclass() {
            	if (skipSuperClasses) {
                	clazz = null;
            	} else {
                	clazz = clazz.getSuperclass();
                	String clazzName = clazz.getName();
                	/** Skip system classes, this just degrades performance. */
                	if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {
                    	clazz = null;
               		 }
            	}
        	} 
            
    }
    
   
    // 解析@Subscribe的核心方法,结果保存再FindState的一个List<SubscriberMethod>属性下面
    private void findUsingReflectionInSingleClass(FindState findState){
        Method[] methods;
        try{
           // 获取class自己声明的方法,包括private的方法; 
            methods = findState.clazz.getDeclaredMethods();
        }catch(Throwable th){
            try{
                //获取class的publish方法,包括继承得来的方法;
                methods = findState.clazz.getMethods();
            }catch(LinkageError error){
                ......
                throw new EventBusException(msg, error);
            }
            findState.skipSuperClasses = true;
        }
        for (Method method : methods){
            int modifiers = method.getModifiers();
            // 通过方法修饰符过滤一下,要public,非abstract,非static, 非synthetic,非bridge,bridge是啥我也不知道
            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0){
                Class<?>[] parameterTypes = method.getParameterTypes();
                // 再过滤一下,只能是参数只有一个的方法,eventbus不支持参数 > 1
                if (parameterTypes.length == 1){
                    // 获取@Subscribe注解对象;
                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                    //有@subscribe,目标命中
                    if (subscribeAnnotation != null){
                        // 该方法只有一个事件对象作为参数,获取事件对象类型;
                        Class<?> eventType = parameterTypes[0];
                        //防止重写父类中的方法造成重复添加;
                        if (findState.checkAdd(method, eventType)){
                            ThreadMode threadMode = subscribeAnnotation.threadMode();
                            // 将@Subscribe注解的解析结果保存到SubscriberMethod对象中;
                            findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
								subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                        }
                    }
                }else if(strictMethodVerification && method.isAnnotationPresent(Subscribe.class)){
                    // 开启严格校验模式下,@Subscribe标记的方法的参数个数不为1会抛异常;
                    ......
                    ......
                    throw new EventBusException("@Subscribe method " + methodName +
					"must have exactly 1 parameter but has " + parameterTypes.length);    
                }  
            }else if(strictMethodVerification && method.isAnnotationPresent(Subscribe.class)){
                // 如果开启了严格校验,@Subscribe标记的方法的修饰符不满足要求会抛异常
                ......
               throw new EventBusException(methodName +" is a illegal @Subscribe method: must be public, non-static, and non-								abstract");     
            }
           
        }
    }
    
    
}
相关推荐
万能的小裴同学6 分钟前
Android M3U8视频播放器
android·音视频
q***577435 分钟前
MySql的慢查询(慢日志)
android·mysql·adb
JavaNoober1 小时前
Android 前台服务 "Bad Notification" 崩溃机制分析文档
android
城东米粉儿2 小时前
关于ObjectAnimator
android
zhangphil3 小时前
Android渲染线程Render Thread的RenderNode与DisplayList,引用Bitmap及Open GL纹理上传GPU
android
火柴就是我4 小时前
从头写一个自己的app
android·前端·flutter
lichong9515 小时前
XLog debug 开启打印日志,release 关闭打印日志
android·java·前端
用户69371750013845 小时前
14.Kotlin 类:类的形态(一):抽象类 (Abstract Class)
android·后端·kotlin
火柴就是我5 小时前
NekoBoxForAndroid 编译libcore.aar
android
Kaede66 小时前
MySQL中如何使用命令行修改root密码
android·mysql·adb