一、先看看EventBus的简单使用
1. 导入eventbus
compile 'org.greenrobot:eventbus:3.0.0'
2. MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//首先要在你要接受EventBus的界面注册,这一步很重要
EventBus.getDefault().register(this);
Button btnCommon = (Button) findViewById(R.id.btn_common);
btnCommon.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_common:
//点击按钮进入CommonActivity
CommonActivity.start(this);
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//在界面销毁的地方要解绑
EventBus.getDefault().unregister(this);
}
//任意写一个方法,给这个方法一个@Subscribe注解,参数类型可以自定义,但是一定要与你发出的类型相同
@Subscribe
public void getEventBus(Integer num) {
if (num != null) {
//这里拿到事件之后吐司一下
Toast.makeText(this, "num" + num, Toast.LENGTH_SHORT).show();
}
}
}
3. CommonActivity
public class CommonActivity extends AppCompatActivity implements View.OnClickListener {
public static void start(Context context) {
context.startActivity(new Intent(context, CommonActivity.class));
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_common);
Button button = (Button) findViewById(R.id.btn_send);
button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_send:
//点击按钮,发送一个int类型的事件
EventBus.getDefault().post(666);
finish();
break;
}
}
}
4. 指定线程执行
//CommonActivity 里面发送消息放到子线程
new Thread(new Runnable() {
@Override
public void run() {
EventBus.getDefault().post(666);
finish();
}
}).start();
//MainActivity里面接收事件,只需要指定线程模式即可,即threadMode = ThreadMode.MAIN-->
@Subscribe(threadMode = ThreadMode.MAIN)
public void getEventBus(Integer num) {
if (num != null) {
Toast.makeText(this, "num" + num, Toast.LENGTH_SHORT).show();
}
}
5. Stick Event(黏性事件)
简单讲,就是在发送事件之后再订阅该事件也能收到该事件,跟黏性广播类似。
1. 先发布事件
//点击按钮,跳转到StickActivity并携带参数,参数类型为String
EventBus.getDefault().postSticky("我是黏性事件");
//开启新的activity
StickActivity.start(this);
2. 在订阅事件
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stick);
//前面也说了,在任何你要接收事件的地方都要先注册
EventBus.getDefault().register(this);
}
//同样的,自定义一个方法,加上 @Subscribe,不同的是在后面再加上一句sticky = true告诉EventBus这是一个粘性事件
@Subscribe(sticky = true)
public void getEventBus(String str) {
Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
}
二、源码分析(EventBus.java)
1. 看看定义的变量
// 一看就是单例
static volatile EventBus defaultInstance;
// 建造者模式
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
// 类型缓存的集合
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
// key 是 Event 参数的类 例如String
// value 存放的是 Subscription 的集合列表
// Subscription 包含两个属性,一个是 subscriber 订阅者(反射执行对象),一个是 SubscriberMethod 注解方法的所有属性参数值
// 发送消息会遍历此集合
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
// key 是所有的订阅者
// value 是所有订阅者里面方法的参数的class 例如String
// 主要用于移除订阅者
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();
}
};
2. 看看注册方法
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
// 拿到类的所以的方法(通过反射方法,然后拿到方法上的注解)
// findSubscriberMethods()去解析注册者对象的所有方法,并且找出带有注解 Subscribe注解的的方法,然后通过Annotation解析所有细节参数(threadMode,priority,sticky,eventType,method),把这些参数封装成一个 SubscriberMethod,添加到集合返回。
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
// 将activity 和注解的方法一一绑定
subscribe(subscriber, subscriberMethod);
}
}
}
3. 看看反射方法的实现
private void findUsingReflectionInSingleClass(FindState findState) {
for (Method method : methods) {
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
// 讲方法上的注解 封装成一个对象 ,存放到集合里面List<SubscriberMethod>
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
}
}
4. 在看看怎么绑定的
// subscriptionsByEventType
// 第一步 讲acitivty 和方法封装成一个对象
// 第二步 讲方法类型 作为key 不同的activity和方法做一个对象放到一个集合里面
// 第三步 按照当前方法的优先级进行集合的存放
// typesBySubscriber
// 将Actvitity作为key eventType存放到一个集合,然后存放到typesBySubscriber
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
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();
for (int i = 0; i <= size; i++) {
// 存放activity +type 按照优先级排序
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
}
5. 简单的例子(subscriptionsByEventType)
将Event的参数类型作为Key,Subscription的集合列表作为Value。然后在post发送内容的时候依据参数的类型去寻找对应的注册者 ,执行对象的方法。结构如下(伪代码)。
// String类型的subscriber
List<Object> mList=new ArrayList<>();
mList.add(new Subscription(MainActivity,test1(String)));
mList.add(new Subscription(MainActivity,test2(String)));
mList.add(new Subscription(MainActivity2,test2(String)));
// int类型的subscriber
List<Object> mList1=new ArrayList<>();
mList1.add(new Subscription(MainActivity,test3(int)));
mList1.add(new Subscription(MainActivity2,test1(int)));
Map<String,List> map=new HashMap<>();
map.put("int",mList1);
map.put("String",mList);
6. 简单的例子 (typesBySubscriber)
将注册者作为Key,参数类型的集合作为Value。这个参数类型的集合针对的是当前注册者中的。 结构如下(伪代码)
List<Object> mList=new ArrayList<>();
mList.add("String");
mList.add("int");
Map<String,List> map=new HashMap<>();
map.put("MainActivity",mList);
7. post()核心的发送代码
public void post(Object event) {
// currentPostingThreadState 是一个 ThreadLocal,
// 他的特点是获取当前线程一份独有的变量数据,不受其他线程影响。
PostingThreadState postingState = currentPostingThreadState.get();
// postingState 就是获取到的线程独有的变量数据
List<Object> eventQueue = postingState.eventQueue;
// 把 post 的事件添加到事件队列
eventQueue.add(event);
// 如果没有处在事件发布状态,那么开始发送事件并一直保持发布状态
if (!postingState.isPosting) {
// 是否是主线程
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
// isPosting = true
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
while (!eventQueue.isEmpty()) {
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
// 如果支持事件继承,默认为支持
if (eventInheritance) {
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
// 依次向 eventClass 的父类或接口的订阅方法发送事件
// 只要有一个事件发送成功,返回 true ,那么 subscriptionFound 就为 true
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
}
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
// 得到Subscription 列表
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
for (Subscription subscription : subscriptions) {
postingState.event = event;
postingState.subscription = subscription;
boolean aborted = false;
try {
postToSubscription(subscription, event, postingState.isMainThread);
aborted = postingState.canceled;
} finally {
postingState.event = null;
postingState.subscription = null;
postingState.canceled = false;
}
if (aborted) {
break;
}
}
return true;
}
return false;
}
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
// 根据不同的线程模式执行对应
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
invokeSubscriber(subscription, event);
break;
case MAIN:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case BACKGROUND:
if (isMainThread) {
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);
}
}
8. unregister(),
在unregister()方法中。调用typesBySubscriber,先通过注册者(MainActivity)找到对应的参数类型集合。然后遍历参数类型集合,拿着参数类型去subscriptionsByEventType找对应的Subscriber。如果Subscriber的注册者是参数类型的注册者,直接移除
/** Unregisters the given subscriber from all event classes. */
public synchronized void unregister(Object subscriber) {
// 获取订阅对象的所有订阅事件类列表
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class<?> eventType : subscribedTypes) {
// 将订阅者的订阅信息移除
unsubscribeByEventType(subscriber, eventType);
}
// 将订阅者从列表中移除
typesBySubscriber.remove(subscriber);
} else {
Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
9. 看看移除的伪代码
//第一步 先查找typesBySubscriber Map 得到一个集合
//传递 MainActivity,查找的是一个list集合 有2个参数类型
//mList.add("String");
//mList.add("int");
//第二步 遍历集合, 拿着类型去subscriptionsByEventType查找
// String 有3个
// mList.add(new Subscription(MainActivity, test1(String)));
// mList.add(new Subscription(MainActivity, test2(String)));
//mList.add(new Subscription(MainActivity2, test2(String)));
//第三步
//有2个与MainActivity一样的都移除。剩下
//mList.add(new Subscription(MainActivity2, test2(String)));
三、手写EventBus
1. 主要手写EventBus.java
/**
* @author 512573717@qq.com
* @created 2018/8/26 上午1:21.
*/
public class EventBus {
// subscriptionsByEventType 这个集合存放的是?
// key 是 Event 参数的类 例如MainActivity里面的 test(String) String
// value 存放的是 Subscription 的集合列表
// Subscription 包含两个属性,一个是 subscriber 订阅者(反射执行对象),一个是 SubscriberMethod 注解方法的所有属性参数值
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
// typesBySubscriber 这个集合存放的是?
// key 是所有的订阅者 MainActivity
// value 是所有订阅者里面方法的参数的class 例如MainActivity里面的 test(String) String
private final Map<Object, List<Class<?>>> typesBySubscriber;
private EventBus() {
typesBySubscriber = new HashMap<Object, List<Class<?>>>();
subscriptionsByEventType = new HashMap<>();
}
static volatile EventBus defaultInstance;
/**
* Convenience singleton for apps using a process-wide EventBus instance.
*/
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
public void register(Object object) {
// 1. 解析所有方法封装成 SubscriberMethod 的集合
List<SubscriberMethod> subscriberMethods = new ArrayList<>();
Class<?> objClass = object.getClass();
Method[] methods = objClass.getDeclaredMethods();
for (Method method : methods) {
//解析所有带有注解的方法
Subscribe subscribe = method.getAnnotation(Subscribe.class);
if (subscribe != null) {
// 所有的Subscribe属性 解析出来
Class<?>[] parameterTypes = method.getParameterTypes();
SubscriberMethod subscriberMethod = new SubscriberMethod(
method, parameterTypes[0], subscribe.threadMode(), subscribe.priority(), subscribe.sticky());
subscriberMethods.add(subscriberMethod);
}
}
// 2. 按照规则存放到 subscriptionsByEventType 里面去
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscriber(object, subscriberMethod);
}
}
// 2. 按照规则存放到 subscriptionsByEventType 里面去
private void subscriber(Object object, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
// 随处能找到,我这个代码
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
}
// 判断优先级 (不写)
Subscription subscription = new Subscription(object, subscriberMethod);
subscriptions.add(subscription);
// typesBySubscriber 要弄好是为了方便移除
List<Class<?>> eventTypes = typesBySubscriber.get(object);
if (eventTypes == null) {
eventTypes = new ArrayList<>();
typesBySubscriber.put(object, eventTypes);
}
if (!eventTypes.contains(eventType)) {
eventTypes.add(eventType);
}
}
public void unregister(Object object) {
List<Class<?>> eventTypes = typesBySubscriber.get(object);
if (eventTypes != null) {
for (Class<?> eventType : eventTypes) {
removeObject(eventType, object);
}
}
}
private void removeObject(Class<?> eventType, Object object) {
// 获取事件类的所有订阅信息列表,将订阅信息从订阅信息集合中移除,同时将订阅信息中的active属性置为FALSE
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 == object) {
// 将订阅信息从集合中移除
subscriptions.remove(i);
i--;
size--;
}
}
}
}
public void post(Object event) {
// 遍历 subscriptionsByEventType,找到符合的方法调用方法的 method.invoke() 执行。要注意线程切换
Class<?> eventType = event.getClass();
// 找到符合的方法调用方法的 method.invoke() 执行
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions != null) {
for (Subscription subscription : subscriptions) {
executeMethod(subscription, event);
}
}
}
private void executeMethod(final Subscription subscription, final Object event) {
ThreadMode threadMode = subscription.subscriberMethod.threadMode;
boolean isMainThread = Looper.getMainLooper() == Looper.myLooper();
switch (threadMode) {
case POSTING:
invokeMethod(subscription, event);
break;
case MAIN:
if (isMainThread) {
invokeMethod(subscription, event);
} else {
// 行不行,不行?行?
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
invokeMethod(subscription, event);
}
});
}
break;
case ASYNC:
AsyncPoster.enqueue(subscription, event);
break;
case BACKGROUND:
if (!isMainThread) {
invokeMethod(subscription, event);
} else {
AsyncPoster.enqueue(subscription, event);
}
break;
}
}
private void invokeMethod(Subscription subscription, Object event) {
try {
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
2. 调用(MainActivity)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 注册,思考为什么要注册?
EventBus.getDefault().register(this);
// 进入测试界面
mTv = (TextView) findViewById(R.id.test_tv);
mTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, TestActivity.class);
startActivity(intent);
}
});
}
/**
* threadMode 执行的线程方式
* priority 执行的优先级
* sticky 粘性事件
*/
@Subscribe(threadMode = ThreadMode.MAIN, priority = 50, sticky = true)
public void test1(String msg) {
// 如果有一个地方用 EventBus 发送一个 String 对象,那么这个方法就会被执行
Log.e("TAG", "msg1 = " + msg);
mTv.setText(msg);
}
@Override
protected void onDestroy() {
// 解绑,思考为什么要解绑?
EventBus.getDefault().unregister(this);
super.onDestroy();
}
3. 调用(TestActivity)
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.test_tv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().post("text");
}
});
}
4. 执行结果
29731-29731/demo.dhcc.com.eventbusdemo E/TAG: msg1 = text
4. 总结
主要的是使用反射,存储app中所有注册过的activity或者Fragment,在发生消息的时候去遍历这个map执行响应的方法。