闲得发慌,打算自己做一个注解+事件总线的android框架
就先从分析一下其他框架开始
EventBus特点
依赖注解(下面是详细在EventBus存在的可注解主题)
Annotation | Feature |
---|---|
@Subscribe | 订阅事件 |
ThreadMode | Description | NOTE |
---|---|---|
POSTING | 直接执行 | 直接通过java.lang.reflect包的method.invoke执行(默认) |
MAIN | 在主线程执行 | EventBus会先判断是否在主线程:是,则直接跟POSTING一样通过method.invoke直接执行;否,则压入mainPoster的队列里 |
MAIN_ORDERED | 同样是在主线程执行 | EventBus压入mainPoster的队列中 |
BACKGROUND | 后台运行 | EventBus会先判断是否在主线程:是,则压入backgroundPoster的队列里;否,则通过method.invoke直接执行 |
ASYNC | 在单独一个线程中执行 | 由EventBusBuilder中的newCachedThreadPool执行 |
它不像xutils一样,拥有控件和控件事件上的注解
不过毕竟是可以跨android和Java的框架
EventBus is a publish/subscribe event bus for Android and Java.
也就不强求这个了(熟悉一下ClassLoader和InvocationHandlr,也可以自己加这些)
事件管理
这个事件的管理囊括了多线程,CopyOnWriteArrayList(java的concurrent包的一个优化算法),它自己建的队列PendingPostQueue,注解事件监听。
ok,那么详细来分析一下这个框架的源码
有几个重要的类或者接口需要看一下
1. EventBus和对应的建造者EventBusBuilder
2. 各种事件Poster
EventBus的实现是典型的建造者模式(当然也有一些工厂模式和代理模式在里面)
public static EventBusBuilder builder() {
//返回一个新建的EventBusBuilder对象
return new EventBusBuilder();
}
在EventBusBuilder的中,创建了一个默认的可无线扩容的线程池newCachedThreadPool
//在EventBusBuilder中
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
...
public EventBusBuilder executorService(ExecutorService executorService) {
this.executorService = executorService;
return this;
}
...
//在异步事件AsyncPoster中
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
queue.enqueue(pendingPost);
eventBus.getExecutorService().execute(this);
}
...
//在后台事件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);
}
}
}
这个线程主要负责异步事件AsyncPoster和后台事件BackgroundPoster的执行,但在EventBus里还有POSTING,MAIN,MAIN_ORDERED这三个事件,那么它们又是靠什么线程来执行的呢?
这三者其实是基本一致的
只不过是MAIN和MAIN_ORDERED事件会先过一个isMainThread()方法
private boolean isMainThread() {
return mainThreadSupport != null ? mainThreadSupport.isMainThread() : true;
}
那么它是怎么将事件放在主线程运行呢?
首先介绍一下Looper这个东西
简单点理解,Looper其实就是一个死循环,不停遍历内部是否含有未处理的Runnable
也是就是执行消息循环队列MessageQueue的一个线程
而且默认情况下,我们后来新建的线程都是没带消息循环队列MessageQueue
//创建一个Looper对象
Looper.prepare();
//开始执行Looper.loop
Looper.loop();
//返回主线程的Looper对象
Looper.getMainLooper();
这里我们就可以做是否主线程的判断了,但还是没有明白怎么把事件发到主线程上
其实这里应该补充一个东西,HandlerThread & Handler的原理了
(如果你有看过tensorflow的官方demo,就可以发现它的识别线程其实就是一个基于主线程Looper创建的一个HandlerThread)
//HandlerThread其实也是多线程的一种,只不过其他多线程基本都是java自带的,不存在Looper
//而HandlerThread是存于android.os包里的,带了Looper
HandlerThread handlerThread = new HandlerThread("线程名称");
//只有在启动这个线程,对应的Looper对象才能被生成,然后才可以创建以此Looper为底的handler(个人理解,可以把handler当作是Looper的一个外露接口)
handlerThread.start();
//以此Looper为底的handler
Handler handler = new Handler(handlerThread.getLooper());
OR
//以此Looper为底的handler,并且处理消息的分发
Handler handler = new Handler(handlerThread.getLooper(),new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
...
return false;
}
});
虽然,EventBus并没有用HandlerThread.....只是用了 Handler handler = new Handler(Looper.getMainLooper()); 而已!
EventBus的所有事件Poster基本都实现了Runnable(除了MAIN和MAIN_ORDERED事件外,这两个都拿去继承了Handler和实现Poster接口而已)
当然在每个事件Poster都有一个PendingPostQueue(EventBus自建带同步锁和延迟弹出的队列)在存储需要发送的消息(ps:下回再讲)
/*提取消息准备发送*/
/*@param event 为开发者自己创建需要传递的消息*/
static PendingPost obtainPendingPost(Subscription subscription, Object event) {
/*pendingPostPool为存储的消息的数组*/
synchronized (pendingPostPool) {
int size = pendingPostPool.size();
if (size > 0) {
PendingPost pendingPost = pendingPostPool.remove(size - 1);
pendingPost.event = event;
pendingPost.subscription = subscription;
pendingPost.next = null;
return pendingPost;
}
}
return new PendingPost(event, subscription);
}
未完待续...
网友评论