定義
- EventBus是一款A(yù)ndroid下的發(fā)布/訂閱事件總線(xiàn)機(jī)制??梢源鍵ntent、Handler、Broadcast等在Fragment、Activity之間傳遞消息。
優(yōu)點(diǎn):開(kāi)銷(xiāo)小,代碼優(yōu)雅。將發(fā)送者和接受者解耦。
在EventBus中,最重要的是三個(gè)map集合:
//Class<?>:響應(yīng)事件方法參數(shù)的類(lèi)型, Subscription:訂閱對(duì)象subscriber+SubscriberMethod
private final Map<Class<?>,CopyOnWriteArrayList<Subscription>> subscriptionByEventType;
//Object:訂閱對(duì)象,List<Class<?>>:方法參數(shù)的類(lèi)型,
private final Map<Object,List<Class<?>>> typesSubscriber;
//黏性事件
private final Map<Class<?>, Object> stickyEvents;
這里主要畫(huà)圖分析第一個(gè)集合,也是最重要的一個(gè),該集合主要用于事件分發(fā),如圖所示:

eventbus1.png
其余的兩個(gè)集合分別用于解除綁定和黏性事件,這里就不再畫(huà)圖分析了,下面我們開(kāi)始擼代碼
核心代碼
public class EventBus {
static volatile EventBus defaultInstance;
//Class<?>:響應(yīng)事件方法參數(shù)的類(lèi)型, Subscription:訂閱對(duì)象subscriber+SubscriberMethod
private final Map<Class<?>,CopyOnWriteArrayList<Subscription>> subscriptionByEventType;
//Object:訂閱對(duì)象,List<Class<?>>:方法參數(shù)的類(lèi)型,
private final Map<Object,List<Class<?>>> typesSubscriber;
//黏性事件
private final Map<Class<?>, Object> stickyEvents;
private EventBus(){
subscriptionByEventType = new HashMap<>();
typesSubscriber = new HashMap<>();
stickyEvents = new HashMap<>();
}
/**
* 單例不解釋
* @return
*/
public static EventBus getDefault(){
if (defaultInstance == null){
synchronized (EventBus.class){
if (defaultInstance == null){
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
/**
* 注冊(cè)訂閱者
* @param object
*/
public void register(Object object){
//1.解析object中的所有方法,通過(guò)Subscribe注解找到響應(yīng)事件的方法,封裝成SubscriberMethod的集合
List<SubscriberMethod> subscriberMethods = new ArrayList<>();
Class<?> clazz = object.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
Subscribe subscribe = method.getAnnotation(Subscribe.class);
if (subscribe != null){
//獲取參數(shù)類(lèi)型
Class<?>[] parameterTypes = method.getParameterTypes();
/**
* method:響應(yīng)事件的方法
* parameterTypes[0] 該方法的參數(shù),注意這里只能有一個(gè)參數(shù)
* threadMode:線(xiàn)程
* priority:優(yōu)先級(jí)
* sticky:黏性事件
*/
SubscriberMethod subscriberMethod = new SubscriberMethod(method,parameterTypes[0],
subscribe.threadMode(),subscribe.priority(),subscribe.sticky());
subscriberMethods.add(subscriberMethod);
}
}
//2.按照規(guī)則存放進(jìn)subscriptionByEventType
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(object,subscriberMethod);
}
}
private void subscribe(Object object, SubscriberMethod subscriberMethod) {
//方法參數(shù)的類(lèi)型
Class<?> eventType = subscriberMethod.eventType;
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionByEventType.get(eventType);
if (subscriptions == null){
subscriptions = new CopyOnWriteArrayList<>();
subscriptionByEventType.put(eventType,subscriptions);
}
//判斷優(yōu)先級(jí)添加
Subscription subscription = new Subscription(object, subscriberMethod);
// 處理優(yōu)先級(jí)
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, subscription);
break;
}
}
//處理粘性事件
if (subscriberMethod.sticky) {
Object stickyEvent = stickyEvents.get(eventType);
if (stickyEvent !=null){
executeMethod(subscription,stickyEvent);
}
}
//用于注銷(xiāo)
List<Class<?>> eventTypes = typesSubscriber.get(object);
if (eventTypes == null){
eventTypes = new ArrayList<>();
typesSubscriber.put(object,eventTypes);
}
if (!eventTypes.contains(eventType)){
eventTypes.add(eventType);
}
}
/**
* 解除訂閱者,防止內(nèi)存泄漏
* @param object
*/
public void unregister(Object object){
List<Class<?>> eventTypes = typesSubscriber.get(object);
if (eventTypes != null){
for (Class<?> eventType : eventTypes) {
removeObject(eventType,object);
}
}
}
/**
* 移除訂閱者
* @param eventType
* @param object
*/
private void removeObject(Class<?> eventType, Object object) {
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionByEventType.get(eventType);
int size = subscriptions.size();
for (int i = 0; i < size; i++) {
Subscription subscription = subscriptions.get(i);
if (subscription.subscriber == object){
subscriptions.remove(subscription);
i--;
size--;
}
}
}
/**
*事件分發(fā)
* @param event
*/
public void post(Object event){
Class<?> eventType = event.getClass();
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionByEventType.get(eventType);
if (subscriptions != null){
for (Subscription subscription : subscriptions) {
executeMethod(subscription,event);
}
}
}
/**
* 在不同線(xiàn)程執(zhí)行事件
* @param subscription
* @param event
*/
private void executeMethod(final Subscription subscription, final Object event) {
ThreadMode threadMode = subscription.subscriberMethod.threadMode;
boolean isMainThread = Looper.getMainLooper() == Looper.myLooper();
switch (threadMode){
//post的線(xiàn)程
case POSTING:
invokeMethod(subscription,event);
break;
//主線(xiàn)程
case MAIN:
if (isMainThread){
invokeMethod(subscription,event);
}else {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
invokeMethod(subscription,event);
}
});
}
break;
//異步線(xiàn)程
case ASYNC:
AsyncPoster.enqueue(subscription,event);
break;
//后臺(tái)線(xiàn)程(非主線(xiàn)程)
case BACKGROUND:
if (!isMainThread){
invokeMethod(subscription,event);
}else {
AsyncPoster.enqueue(subscription,event);
}
break;
}
}
/**
* 通過(guò)反射執(zhí)行方法
* @param subscription
* @param event
*/
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();
}
}
/**
* 發(fā)送黏性事件
* @param event 訂閱對(duì)象
*/
public void postSticky(Object event) {
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
post(event);
}
/**
* 移除粘性事件
* @param event
* @return
*/
public boolean removeStickyEvent(Object event) {
synchronized (stickyEvents) {
Class<?> eventType = event.getClass();
Object existingEvent = stickyEvents.get(eventType);
if (event.equals(existingEvent)) {
stickyEvents.remove(eventType);
return true;
} else {
return false;
}
}
}
/**
* 移除全部粘性事件
*/
public void removeAllStickyEvents() {
synchronized (stickyEvents) {
stickyEvents.clear();
}
}
/**
* 獲取粘性事件
*/
public <T> T getStickyEvent(Class<T> eventType) {
synchronized (stickyEvents) {
return eventType.cast(stickyEvents.get(eventType));
}
}
/**
* 移除粘性事件
* @param
* @return
*/
public <T> T removeStickyEvent(Class<T> eventType) {
synchronized (stickyEvents) {
return eventType.cast(stickyEvents.remove(eventType));
}
}
}
其中
class AsyncPoster implements Runnable {
Subscription subscription;
Object event;
//Eventbus的源碼中也使用了該線(xiàn)程池
private final static ExecutorService executorService = Executors.newCachedThreadPool();
public AsyncPoster(Subscription subscription, Object event){
this.subscription = subscription;
this.event = event;
}
public static void enqueue(Subscription subscription, Object event) {
AsyncPoster asyncPoster = new AsyncPoster(subscription,event);
// 用線(xiàn)程池
executorService.execute(asyncPoster);
}
@Override
public void run() {
try {
subscription.subscriberMethod.method.invoke(subscription.subscriber,event);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
使用
使用方法與原版EventBus一模一樣
//發(fā)送普通事件
EventBus.getDefault().post("text");
//發(fā)送粘性事件
EventBus.getDefault().postSticky("hi");
//注冊(cè)訂閱
EventBus.getDefault().register(this);
// 解綁
EventBus.getDefault().unregister(this);
/**
* threadMode 執(zhí)行的線(xiàn)程方式
* priority 執(zhí)行的優(yōu)先級(jí)
* sticky 粘性事件
*/
@Subscribe(threadMode = ThreadMode.MAIN,priority = 50,sticky = true)
public void test1(String msg){
// 如果有一個(gè)地方用 EventBus 發(fā)送一個(gè) String 對(duì)象,那么這個(gè)方法就會(huì)被執(zhí)行
Log.e("TAG","msg1 = "+msg);
mTv.setText(msg);
}
/**
* threadMode 執(zhí)行的線(xiàn)程方式
* priority 執(zhí)行的優(yōu)先級(jí),值越大優(yōu)先級(jí)越高
* sticky 粘性事件
*/
@Subscribe(threadMode = ThreadMode.MAIN,priority = 100,sticky = true)
public void test2(String msg){
// 如果有一個(gè)地方用 EventBus 發(fā)送一個(gè) String 對(duì)象,那么這個(gè)方法就會(huì)被執(zhí)行
Log.e("TAG","msg2 = "+msg);
mTv.setText(msg);
}