不,这只是个名字,一个代号,你可以叫,我也可以叫
最后编辑于2019年4月25日
提到事件总线我们总会想到EventBus和Otto,他们之间的区别是:
1、Otto可以使用@Produce的方式来发布事件;
2、EventBus提供了单例模式;
3、EventBus支持threadMode;
4、EventBus支持优先级;
5、EventBus支持编译时把订阅方法放到集合中等待调用合并成新的集合;
6、EventBus支持黏性事件。
今天这个吕秀才说死姬无命的故事就可以套用到黏性事件上。什么是黏性事件?先发送了事件后订阅对象,仍能触发订阅方法的事件就叫做黏性事件了。
一、先简单分析一下eventbus怎么处理普通事件的。
step1:订阅者注册,分为两步,一是查找订阅者的订阅方法,二是把方法按不同事件封装到一个集合中,并把方法按不同订阅对象封装到另一个集合中。
stepA:查找订阅者的方法,根据用户设置的ignoreGeneratedIndex,决定是通过反射的方法来获取订阅者方法,还是通过调用编译时生成的class中的方法来获取订阅者方法。
下面是通过反射的方法来获取订阅者方法:
而通过编译时生成的class中的方法来获取订阅者方法,则需要用户先使用以下代码:
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
// 这里是获取一个单例
EventBus eventBus = EventBus.getDefault();
这样就把订阅者及订阅者方法SimpleSubscriberInfo放到subscriberInfoIndexs里了,如下面两张图:
通过findUsingInfo()方法分两步获取到订阅者方法,一、把subscriberInfoIndexes中的信息放到SubscriberInfo中,二、从SubscriberInfo中获取订阅者方法。如下面三张图:
stepB:把方法按不同事件封装到一个集合subscriptionsByEventType中,并把方法按不同订阅对象封装到另一个集合typesBySubscriber中:如下图:
step2:事件的发送
通过post()、postSingleEvent()、postSingleEventForEventType()、postToSubscription()、invokeSubscriber()几个方法的传递,最终事件的发送触发了订阅方法的调用,如下面几张图:
step3: 订阅者取消注册
分为两步,把该对象下的按事件分类的订阅从subscriptionsByEventType中移除,把该订阅对象下的订阅从typesBySubscriber中移除,如下面两张图:
eventbus怎么处理普通事件的简易过程就讲完了(我只是想讲一个黏性事件的,结果讲了这么多,暴汗2333)。
二、黏性事件的处理
先发送了事件后注册订阅对象,仍能触发订阅方法的事件就叫做黏性事件了。
后注册订阅怎么还能触发呢?其实这个时候黏性事件反而成了订阅对象,当注册时就会调用黏性事件相关的订阅方法。
不,这只是个名字,一个代号,你可以叫订阅对象,我也可以叫订阅对象。
三、再举个例子
Person都有YoungState、OldState两种状态可以这么写:
public class Person {
private State state;
public void setState(State state) {
this.state = state;
}
public void brush() {
state.brush();
}
}
public interface State {
void brush();
}
public class YoungState implements State {
@Override
public void brush() {
System.out.println("年轻人刷牙");
}
}
public class OldState implements State {
@Override
public void brush() {
System.out.println("老年人刷牙");
}
}
在此基础上可以很轻松地加一个childState:
public class ChildState implements State {
@Override
public void brush() {
System.out.println("小孩刷牙");
}
}
但是如果要你增加wash、eat、run几个方法呢,像下面这样吗?
public class Person {
private State state;
public void setState(State state) {
this.state = state;
}
public void brush() {
state.brush();
}
public void wash() {
state.wash();
}
public void eat() {
state.eat();
}
public void run() {
state.run();
}
}
public interface State {
void brush();
void wash();
void eat();
void run();
}
public class YoungState implements State {
@Override
public void brush() {
System.out.println("年轻人刷牙");
}
@Override
public void wash() {
System.out.println("年轻人洗脸");
}
@Override
public void eat() {
System.out.println("年轻人吃饭");
}
@Override
public void run() {
System.out.println("年轻人跑步");
}
}
public class OldState implements State {
@Override
public void brush() {
System.out.println("老年人刷牙");
}
@Override
public void wash() {
System.out.println("老年人洗脸");
}
@Override
public void eat() {
System.out.println("老年人吃饭");
}
@Override
public void run() {
System.out.println("老年人跑步");
}
}
但其实还可以换个角度,把brush、wash、eat、run当作一种状态:
public class Person {
private State state;
public void setState(State state) {
this.state = state;
}
public void young() {
state.young();
}
public void old() {
state.old();
}
}
public interface State {
void young();
void old();
}
public class BrushState implements State {
@Override
public void young() {
System.out.println("年轻人刷牙");
}
@Override
public void old() {
System.out.println("老年人刷牙");
}
}
public class WashState implements State {
@Override
public void young() {
System.out.println("年轻人洗脸");
}
@Override
public void old() {
System.out.println("老年人洗脸");
}
}
public class EatState implements State {
@Override
public void young() {
System.out.println("年轻人吃饭");
}
@Override
public void old() {
System.out.println("老年人吃饭");
}
}
public class RunState implements State {
@Override
public void young() {
System.out.println("年轻人跑步");
}
@Override
public void old() {
System.out.println("老年人跑步");
}
}
不,这只是个名字,一个代号,你可以叫状态,我也可以叫状态。
四、再再举个例子
AIDL中客户端可以变为服务端,服务端也可以变为客户端,通过aidl调用远程服务 。