什么是EventBus
EventBus是基于事件总站的方式接收Publisher发布的消息,然后回调各个订阅者的相关订阅函数,这样可以有效的解耦发布者和订阅者在 Android中的事件传递关系。
相关对象
Event:就是Publisher发布的某一种类型对象。
EventBus:事件总站,用于存贮订阅者对某个事件类型的注册信息。
Subscriber:对某种类型的对象进行订阅,也就是在EventBus中进行注册。Publisher发布此类对象时,EventBus 会执行Subscriber的一些列 onEvent 函数。订阅者通过 register 接口订阅某个事件类型,unregister 接口退订。
Publisher:发布某Event对象,通过 post 方法发布Event。
流程图
大概的情况介绍完了,下面通过例子来介绍:
Subscriber是一个简单的Activity,在onCreate中注册,在onDestroy中注销
public class DemoActivity extends BaseActivity implements DataListener,View.OnClickListener {
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
MyBus.get().register(this);
}
@Override
public void initView() {
button = (Button)findViewById(R.id.buton);
}
@Override
public void initOnClickListener() {
button.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.buton:
startActivity(new Intent(this,SonActivity.class));
break;
}
}
@Override
protected void onDestroy(){
super.onDestroy();
}
public void onEvent(String postStr){
button.setText(postStr);
}
}
代码很简单,就是注册和反注册,然后里面的注册函数为onEvent,参数时String类型的。
下面看看注册函数是什么样的
public void register(Object subscriber) {
Class<?> clazz = subscriber.getClass();
Method[] methods = clazz.getMethods();
for (Method m : methods) {
String name = m.getName();
if (name.startsWith("onEvent")) {
SubInfo subInfo = new SubInfo();
subInfo.subscriber = subscriber;
subInfo.method = m;
if (isExist(m)) {
isRegister(m).subscriberList.add(subInfo);
} else {
Class<?>[] params = m.getParameterTypes();
Subscription subscription = new Subscription();
subscription.clazz = params[0];
subscription.subscriberList = new ArrayList<>();
subscription.subscriberList.add(subInfo);
classInfoList.add(subscription);
}
}
}
}
rivate Subscription isRegister(Method m) {
Subscription subscription = new Subscription();
Class<?>[] params = m.getParameterTypes();
if (isExist(m)) {
for (Subscription subs : classInfoList) {
if (subs.clazz == params[0]) {
subscription = subs;
break;
}
}
}
return subscription;
}
private boolean isExist(Method m) {
boolean isExist = false;
Class<?>[] params = m.getParameterTypes();
for (Subscription subs : classInfoList) {
if (subs.clazz == params[0]) {
isExist = true;
break;
}
}
return isExist;
}
利用反射原理得到Subscriber以onEvent开头的注册函数以及第一个参数,如果这个参数类型的已经存在了就把原来以及注册过这个参数的对象拿出来,加到订阅者list中去,如果不存在,声明一个这个类型的注册对象,并将这个订阅者加到这个类型的订阅者list中去,
public class Subscription {
Class<?> clazz;
List<SubInfo> subscriberList;
}
下面是注销函数
public void unregister(String name, Class<?>[] params) {
for (Subscription subs : classInfoList) {
if (subs.clazz == params[0]) {
for (int i = 0; i < subs.subscriberList.size(); i++) {
if (subs.subscriberList.get(i).method.equals(name)) {
subs.subscriberList.remove(i);
}
}
break;
}
}
}
public void unRegister(Object subscriber) {
Class<?> clazz = subscriber.getClass();
Method[] methods = clazz.getMethods();
for (Method m : methods) {
String name = m.getName();
Class<?>[] params = m.getParameterTypes();
if (name.startsWith("onEvent")) {
unregister(name, params);
}
}
}
然后发布
MyBus.get().post(“post success”);
再看看是怎么样实现发布函数执行的
public void post(Object event) {
Class<?> clazz = event.getClass();
Subscription subscription = null;
for(int i=0 ;i< classInfoList.size();i++){
if(classInfoList.get(i).clazz == clazz){
subscription = classInfoList.get(i);
}
}
if(subscription != null) {
postSub(subscription,event);
}
}
private void postSub(Subscription subscription,Object event){
List<SubInfo> subscriptionList = subscription.subscriberList;
for(int i = 0;i<subscriptionList.size();i++){
SubInfo subInfo = subscriptionList.get(i);
MyPostThread.post(subInfo,event);
}
}
看看MyPostThread这个类
public class MyPostThread{
MyPostThread() {
}
public static void post(SubInfo subInfo,Object event){
MyBus.get().invoke(subInfo,event, subInfo.method);
}
}
最后还是利用反射原理的相关函数完成注册者的注册函数调用
public void invoke(final SubInfo sub, final Object event,Method m){
try {
m.invoke(sub.subscriber,event);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
Ok,代码到这里就完成了,有兴趣的同学可以试一下。