路漫漫其修遠(yuǎn)兮
01. 手寫EventBus框架——源碼分析1
02. 手寫EventBus框架——源碼分析2
03. 手寫EventBus框架——動手_整體架構(gòu)設(shè)計(jì)
04. 手寫EventBus框架——動手_終結(jié)
o.O前戲已經(jīng)足夠了,接下來擼 代碼了。
主體框架
類設(shè)計(jì)

第一版結(jié)構(gòu)
EventBus.class
/**
* <p/>
* Author: 溫利東 on 2017/3/26 10:44.
* blog: http://www.itdecent.cn/u/99f514ea81b3
* github: https://github.com/LidongWen
*/
public class EventBus {
private static EventBus ourInstance;
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> cacheMap;
private final Map<Object, List<Class<?>>> typesBySubscriber;
//粘性
private final Map<Class<?>, Object> stickyEvents;
public static EventBus getDefault() {
if (ourInstance == null) {
synchronized (EventBus.class) {
if (ourInstance == null) {
ourInstance = new EventBus();
}
}
}
return ourInstance;
}
private EventBus() {
//初始化一些數(shù)據(jù)
cacheMap = new HashMap<>();
stickyEvents = new ConcurrentHashMap<>();
typesBySubscriber=new HashMap<>();
}
public void register(Object subscriber) {
//1.找到所有方法
//2.保存訂閱 subscriber();
}
public void unRegister(Object subscriber) {
//去除訂閱
}
public void post(Object obj) {
//1.獲取緩存 進(jìn)行判斷
//2.指定線程執(zhí)行
}
public void postSticky(Object obj){
//加入粘性緩存 stickyEvents
//執(zhí)行
}
/**
* 保存訂閱方法
* @param subscriber
*/
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//1.保存數(shù)據(jù) , 如果重復(fù) 拋異常
//2.執(zhí)行粘性事件
}
}
線程枚舉類
public enum ThreadMode {
POSTING,
MAIN,
BACKGROUND,
ASYNC
}
注解類
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
//粘性
boolean sticky() default false;
//優(yōu)先級
int priority() default 0;
}
訂閱元元素類 SubscriberMethod ;
/**
* <p/>
* Author: 溫利東 on 2017/3/23 17:56.
* blog: http://blog.csdn.net/sinat_15877283
* github: https://github.com/LidongWen
*/
public class SubscriberMethod {
final Method method;
final ThreadMode threadMode;
final Class<?> eventType; //參數(shù)
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;
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
} else if (other instanceof SubscriberMethod) {
checkMethodString();
SubscriberMethod otherSubscriberMethod = (SubscriberMethod) other;
otherSubscriberMethod.checkMethodString();
// Don't use method.equals because of http://code.google.com/p/android/issues/detail?id=7811#c6
return methodString.equals(otherSubscriberMethod.methodString);
} else {
return false;
}
}
private synchronized void checkMethodString() {
if (methodString == null) {
// Method.toString has more overhead, just take relevant parts of the method
StringBuilder builder = new StringBuilder(64);
builder.append(method.getDeclaringClass().getName());
builder.append('#').append(method.getName());
builder.append('(').append(eventType.getName());
methodString = builder.toString();
}
}
@Override
public int hashCode() {
return method.hashCode();
}
}
擴(kuò)展框架設(shè)計(jì)_01
以上整體的一個架構(gòu)就出來了,可以看出來,整體的邏輯都在EventBus類里面,雖然其中都是些偽代碼,但代碼量還是很大的,那么我們可以抽出一些偽代碼作為幫助類;
- 訂閱方法查找類;
SubscriberMethodFinder.class; - 方法執(zhí)行幫助類;
InvokeHelper.class;
那么結(jié)構(gòu)就變成這樣了

InvokeHelper.class
/**
* 方法執(zhí)行幫助類
* <p/>
* Author: 溫利東 on 2017/3/26 11:29.
* blog: http://www.itdecent.cn/u/99f514ea81b3
* github: https://github.com/LidongWen
*/
public class InvokeHelper {
public static void post(SubscriberMethod subscriberMethod,Object event, boolean isMainThread) {
switch (subscriberMethod.threadMode) {
case POSTING:
//直接執(zhí)行
break;
case MAIN:
if (isMainThread) {
//直接執(zhí)行
} else {
// 放在handler內(nèi)執(zhí)行
}
break;
case BACKGROUND:
if (isMainThread) {
//放在后臺線程執(zhí)行
} else {
//執(zhí)行
}
break;
case ASYNC:
//放在異步線程內(nèi)執(zhí)行
break;
default:
//拋異常
throw new IllegalStateException("Unknown thread mode: " + subscriberMethod.threadMode);
}
}
}
SubscriberMethodFinder.class
/**
* 訂閱方法查找類
* <p/>
* Author: 溫利東 on 2017/3/26 11:21.
* blog: http://www.itdecent.cn/u/99f514ea81b3
* github: https://github.com/LidongWen
*/
public class SubscriberMethodFinder {
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
/**
* 查找方法
* @param subscriberClass
* @return
*/
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
return null;
}
}
擴(kuò)展框架設(shè)計(jì)_02
- 異步線程
AsyncPoster - 順序執(zhí)行
BackgroundPoster
這下子架構(gòu)就變成這樣了

/**
* //異步線程
* <p/>
* Author: 溫利東 on 2017/3/26 17:36.
* blog: http://www.itdecent.cn/u/99f514ea81b3
* github: https://github.com/LidongWen
*/
public class AsyncPoster implements Runnable {
@Override
public void run() {
}
}
/**
* Posts events in background.
* <p/>
* Author: 溫利東 on 2017/3/26 17:36.
* blog: http://www.itdecent.cn/u/99f514ea81b3
* github: https://github.com/LidongWen
*/
final class BackgroundPoster implements Runnable {
@Override
public void run() {
}
}
還漏了一個 Subscription.class 這里加上

Subscription.class
final class Subscription {
final Object subscriber;
final SubscriberMethod subscriberMethod;
volatile boolean active;
Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
this.subscriber = subscriber;
this.subscriberMethod = subscriberMethod;
active = true;
}
@Override
public boolean equals(Object other) {
if (other instanceof Subscription) {
Subscription otherSubscription = (Subscription) other;
return subscriber == otherSubscription.subscriber
&& subscriberMethod.equals(otherSubscription.subscriberMethod);
} else {
return false;
}
}
@Override
public int hashCode() {
return subscriber.hashCode() + subscriberMethod.methodString.hashCode();
}
}
好了 現(xiàn)在我們簡易版EventBus框架結(jié)構(gòu)就搭建起來了。其中沒有實(shí)現(xiàn)代碼,全是偽代碼邏輯。其實(shí)寫到這里,各位都可以自己敲代碼來實(shí)現(xiàn)具體的功能了。
下一節(jié)我們將完成以及完善我們簡易版EventBus的功能了。
下一節(jié): 04. 手寫EventBus框架——動手_終結(jié)
希望我的文章不會誤導(dǎo)在觀看的你,如果有異議的地方歡迎討論和指正。
如果能給觀看的你帶來收獲,那就是最好不過了。