EventBus事件总线框架
EventBus项目地址
EventBus源码解析(二)
EventBus源码解析(三)EventBus类
EventBus实战
自定义RxBus + RxRelay
RxRelay源码解析
EventBus基于事件的订阅和推送,实现Activity/Fragment之间的通信。
主要角色:
- Event 传递的事件对象,自定义的一个类,封装了要传递的信息。
- Publisher 事件的发布者EventBus,可以在任意线程任意位置发送事件。
- Subscriber 事件的订阅者Activiyt/Fragment。
- ThreadMode 定义在何种线程中发送事件。
EventBus源码地址
源码解析:
1.Subscription类
/**
* 订阅者信息
*/
final class Subscription {
final Object subscriber; //订阅者
final SubscriberMethod subscriberMethod; //订阅方法
volatile boolean active; //是否在订阅状态,EventBus#unregister(Object)} is false
Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
this.subscriber = subscriber;
this.subscriberMethod = subscriberMethod;
active = true;
}
}
2.ThreadMode枚举类
public enum ThreadMode {
/**
* Subscriber将在同一线程中直接调用,其用于发送事件. 默认.
*/
POSTING,
/**
* 主线程调用,注意防止阻塞线程.
*/
MAIN,
/**
* 主线程调用,有序,避免了阻塞
*/
MAIN_ORDERED,
/**
* 若在主线程调用将启用一条后台线程;若在其他线程调用,直接在当前线程调用
*/
BACKGROUND,
/**
* 异步线程,不会造成阻塞,用于耗时较长
*/
ASYNC
}
3.MainThreadSupport 接口
/**
* 主线程支持
*/
public interface MainThreadSupport {
boolean isMainThread();
Poster createPoster(EventBus eventBus); //创建一个Poster
/**
* 主线程支持类
*/
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);
}
}
}
4.SubscriberMethod
/**
* 订阅方法信息
*/
public class SubscriberMethod {
final Method method; //订阅方法
final ThreadMode threadMode; //指定发送事件的线程模式
final Class<?> eventType; //订阅事件的类型
final int priority; //订阅者级别
final boolean sticky; //是否接收sticky事件
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;
}
}
5.SubscriberMethodFinder
/**
* 查找订阅者的所有订阅方法
*/
class SubscriberMethodFinder {
...省略部分代码
//订阅此事件的所有方法 key:eventType value:方法集合
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
private final boolean ignoreGeneratedIndex; //是否忽略注解
//以订阅者类型 查找它的 所有订阅者方法信息
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
//若忽略注解,则反射出方法
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass);
} else {
subscriberMethods = findUsingInfo(subscriberClass);
}
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;
}
}
//订阅此事件的所有方法清空
static void clearCaches() {
METHOD_CACHE.clear();
}
6.PendingPost
**
* 待发送事件,这个事件将会被加入事件池
* 封装了事件event,订阅者信息subscription
*/
public class PendingPost {
//事件池
private final static List<PendingPost> pendingPostPool = new ArrayList<>(); //事件池
Object event; //事件
Subscription subscription; //订阅信息
PendingPost next;
private PendingPost(Object event, Subscription subscription) {
this.event = event;
this.subscription = subscription;
}
/**
* 获取一个指定subscription和event的待发送事件PendingPost
* @param subscription 订阅者信息
* @param event 事件
*/
static PendingPost obtainPendingPost(Subscription subscription, Object event) {
synchronized (pendingPostPool) {
int size = pendingPostPool.size();
if (size > 0) {
//取出最后一个位置的PendingPost向其赋值
PendingPost pendingPost = pendingPostPool.remove(size - 1);
pendingPost.event = event;
pendingPost.subscription = subscription;
pendingPost.next = null;
return pendingPost;
}
}
//若事件池为空,创建一个新的PendingPost
return new PendingPost(event, subscription);
}
//释放这个待发送事件PendingPost
static void releasePendingPost(PendingPost pendingPost) {
pendingPost.event = null;
pendingPost.subscription = null;
pendingPost.next = null;
synchronized (pendingPostPool) {
// 不要让事件池无限增长
if (pendingPostPool.size() < 10000) {
pendingPostPool.add(pendingPost);
}
}
}
}
7.PendingPostQueue
/**
* 同步发送事件队列,包含两个PendingPost
*/
public class PendingPostQueue {
private PendingPost head;
private PendingPost tail;
//执行发送指定的pendingPost
synchronized void enqueue(PendingPost pendingPost) {
if (pendingPost == null) {
throw new NullPointerException("null cannot be enqueued");
}
//若已经有两个pendingPost待发送,替换tail为我指定发送的pendingPost,并存入tail.next
if (tail != null) {
tail.next = pendingPost;
tail = pendingPost;
//若队列为空,直接入队列head,tail都为pendingPost
} else if (head == null) {
head = tail = pendingPost;
} else {
throw new IllegalStateException("Head present, but no tail");
}
notifyAll();
}
//取出head处pendingPost,head和tail为空
synchronized PendingPost poll() {
PendingPost pendingPost = head;
if (head != null) {
head = head.next;
if (head == null) {
tail = null;
}
}
return pendingPost;
}
//递归调用,每隔一段时间拉取一次PendingPost
synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {
if (head == null) {
wait(maxMillisToWait);
}
return poll();
}
}
8.Poster接口
/**
* 发射器:发送event事件
*/
public interface Poster {
/**
* 执行发送/订阅
* @param subscription 订阅者信息
* @param event 订阅的事件
*/
void enqueue(Subscription subscription, Object event);
}
9.AsyncPoster异步,BackgroundPoster后台,HandlerPoster主线程
/**
* 异步发送事件,反射调用订阅者的订阅方法,来订阅event。
*/
public class AsyncPoster implements Runnable,Poster {
private final PendingPostQueue queue; //待发送队列
private final EventBus eventBus;
AsyncPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
}
/**
* 执行发送
* @param subscription 已经调用subscribe形成订阅
* @param event
*/
public void enqueue(Subscription subscription, Object event) {
//封装subscription和event为待发送事件pendingPost
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
//入队列
queue.enqueue(pendingPost);
//将此异步发送线程(run()方法)放入线程池执行
eventBus.getExecutorService().execute(this);
}
@Override
public void run() {
//从队列拉取要发送的pendingPost
PendingPost pendingPost = queue.poll();
if(pendingPost == null) {
throw new IllegalStateException("No pending post available");
}
//反射调用订阅者的订阅方法,来订阅event。即形成一个订阅通路
eventBus.invokeSubscriber(pendingPost);
}
}