EventBus源码分析
我分析源码一般是从整体来进行分析,对于一些细节的东西,我没有时间也没有能力去分析。
简单使用
导入依赖
implementation'org.greenrobot:eventbus:3.1.1'
定义观察者
public class MyObserver1 {
public MyObserver1() {
EventBus.getDefault().register(this);
}
@Subscribe
public void myEvent(MyEvent event){
System.out.println("我是观察者1,我观察到了");
}
}
public class MyObserver2 {
public MyObserver2() {
EventBus.getDefault().register(this);
}
@Subscribe
public void myEvent(MyEvent event) {
System.out.println("我是观察者2,我观察到了");
}
}
定义被观察者和测试
public class MyObserved {
public MyObserver1 observer1;
public MyObserver2 observer2;
public MyObserved() {
observer1 = new MyObserver1();
observer2 = new MyObserver2();
}
public static void main(String[] args) {
MyObserved observed = new MyObserved();
Scanner in = new Scanner(System.in);
while (true) {
int code = in.nextInt();
if (code == 1) {
observed.sendEvent();
} else {
EventBus.getDefault().unregister(observed.observer1);
EventBus.getDefault().unregister(observed.observer2);
break;
}
}
}
public void sendEvent() {
MyEvent event = new MyEvent();
EventBus.getDefault().post(event);
}
}
输出
1
我是观察者1,我观察到了
我是观察者2,我观察到了
1
我是观察者1,我观察到了
我是观察者2,我观察到了
2
具体分析
这里就从上面使用到的方法来进行分析。
入口方法
getDefault()
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
这里就是采用双重校验并加锁(DCL)的单例模式生成EventBus实例。
注册
register()
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
findSubscriberMethods(Class<?> subscriberClass)
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);
}
//。。。省略
}
findUsingReflection(Class<?> subscriberClass)
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
//...
findUsingReflectionInSingleClass(findState);
//...
}
findUsingReflectionInSingleClass(FindState findState)
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
for (Method method : methods) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
findState.subscriberMethods.add(new SubscriberMethod(method, eventType,threadMode,subscribeAnnotation.priority(),subscribeAnnotation.sticky()));
}
}
}
//...
}
以上几个方法的大致逻辑就是先看有没有SubscriberMethod的缓存,有的话直接用,没有的话就找出添加了@Subscribe注解的方法。在findUsingReflectionInSingleClass方法里也可以看到很明显的以反射机制处理注解的逻辑。
SubscriberMethod类
public class SubscriberMethod {
final Method method;
final ThreadMode threadMode;
final Class<?> eventType;
final int priority;
final boolean sticky;
/** Used for efficient comparison */
String methodString;
//...
}
从成员变量可以看出这个SubscriberMethod是用来封装观察者的添加了Subscribe注解的方法,观察者有一个观察方法就有一个SubscriberMethod。
最终封装
上面的register方法只看了一部分,还有下面一部分。
public void register(Object subscriber) {
//...
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
这里将观察者的每个观察方法进行最终封装。
subscribe(Object subscriber, SubscriberMethod subscriberMethod)
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);
}
}
//。。。
}
上面的逻辑就是为了避免二次注册,而我省略的部分可以总结为将Subscription添加进容器里。
Subscription类
final class Subscription {
final Object subscriber;
final SubscriberMethod subscriberMethod;
//...
}
主要封装了观察者对象和其方法
EventBus有个关键的成员变量:
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
这个Map以事件类型为键,对应的观察方法的容器为值。
而Subscription封装好了之后就是放入这个Map里的。
发送
post()
public void post(Object event) {
PostingThreadState postingState = currentPostingThreadState.get();
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event);
if (!postingState.isPosting) {
postingState.isMainThread = isMainThread();
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;
}
}
}
post主要逻辑就是根据传入的事件,根据其事件类型(Class<?>)从subscriptionsByEventType取出对应事件类型的Subscription,然后利用反射机制,调用方法。
仿EventBus实现
这里就根据上面的分析来实现一个简单的EventBus。
构造单例对象
private HashMap<Class<?>, ArrayList<Observation>> mObserverArrayListHashMap;
private MyEventBus() {
mObserverArrayListHashMap = new HashMap<>();
}
public static MyEventBus getDefault() {
return SingletonHolder.SINGLETON;
}
private static class SingletonHolder {
private static final MyEventBus SINGLETON = new MyEventBus();
}
这里我采用静态内部类的方式实现单例模式
注册
public void register(Object observer) {
Class<?> observerClass = observer.getClass();
List<ObserverMethod> observerMethods = findObserverMethods(observerClass);
for (ObserverMethod observerMethod : observerMethods) {
observe(observer, observerMethod);
}
}
private List<ObserverMethod> findObserverMethods(Class<?> observerClass) {
List<ObserverMethod> observerMethods = new ArrayList<>();
for (Method method : observerClass.getDeclaredMethods()) {
Observe observe = method.getAnnotation(Observe.class);
if (observe != null) {
Class<?> eventType = method.getParameterTypes()[0];
ObserverMethod observerMethod = new ObserverMethod(method, eventType);
observerMethods.add(observerMethod);
}
}
return observerMethods;
}
private void observe(Object observer, ObserverMethod observerMethod) {
Class<?> eventType = observerMethod.getEventType();
Observation observation = new Observation(observer, observerMethod);
ArrayList<Observation> observations = mObserverArrayListHashMap.get(eventType);
if (observations == null) {
observations = new ArrayList<>();
mObserverArrayListHashMap.put(eventType, observations);
} else {
if (observations.contains(observation)) {
return;
}
}
observations.add(observation);
}
两个封装类
class ObserverMethod {
private Method mMethod;
private Class<?> mEventType;
public ObserverMethod(Method method, Class<?> eventType) {
mMethod = method;
this.mEventType = eventType;
}
public Method getMethod() {
return mMethod;
}
public Class<?> getEventType() {
return mEventType;
}
}
class Observation {
private Object observer;
private ObserverMethod observerMethod;
public Observation(Object observer, ObserverMethod observerMethod) {
this.observer = observer;
this.observerMethod = observerMethod;
}
public Object getObserver() {
return observer;
}
public ObserverMethod getObserverMethod() {
return observerMethod;
}
}
发送
public void post(Object event) {
Class<?> eventType = event.getClass();
ArrayList<Observation> observations = mObserverArrayListHashMap.get(eventType);
if (observations == null) {
return;
}
for (Observation observation : observations) {
Object observer = observation.getObserver();
Method method = observation.getObserverMethod().getMethod();
try {
method.invoke(observer, event);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
测试
观察者
public class MyObserver1 {
public MyObserver1() {
MyEventBus.getDefault().register(this);
}
@Observe
public void myEvent(MyEvent event){
System.out.println("我是观察者1,我观察到了");
}
}
public class MyObserver2 {
public MyObserver2() {
MyEventBus.getDefault().register(this);
}
@Observe
public void myEvent(MyEvent event){
System.out.println("我是观察者2,我观察到了");
}
}
事件
public class MyEvent {
}
被观察者及测试
public class MyObserved {
public MyObserved() {
MyObserver1 observer1 = new MyObserver1();
MyObserver2 observer2 = new MyObserver2();
}
public static void main(String[] args) {
MyObserved observed = new MyObserved();
Scanner in = new Scanner(System.in);
while (true) {
int code = in.nextInt();
if (code == 1) {
observed.sendEvent();
} else {
break;
}
}
}
public void sendEvent() {
MyEvent event = new MyEvent();
MyEventBus.getDefault().post(event);
}
}
output:
1
我是观察者1,我观察到了
我是观察者2,我观察到了
1
我是观察者1,我观察到了
我是观察者2,我观察到了
2
Process finished with exit code 0
网友评论