一、实现原理
1、主要的实现类为EventBus类,用观察者实际模式来实现(观察者设计模式参考),包含三个主要的方法:register、 unregister、post
2、订阅者(一般为activity)通过EventBus的register和unRegister来订阅和取消订阅
3、事件发布者通过post来发布数据,EventBus找到自己缓存的所有订阅者,并找到每一个订阅者的所有方法并执行
二、订阅
1、activity把自己作为订阅者,注册到EventBus中,当事件产生时,会调用activity中指定的方法。为了能准确找到需要被调用的方法,这里需要用到自定义注解。
(1)、注册订阅者,activity的onCreate中调用 EventBus.getDefault().register(this);
(2)、自定义注解的实现
@Target({ElementType.METHOD}) // 注解用到方法上的
@Retention(RetentionPolicy.RUNTIME) // 运行时起作用
public @interface Subscrible {
ThreadMode threadMode() default ThreadMode.MAIN;
}
(3)、订阅者方法的实现
// MainActivity方法放到eventbus中,
// 并不是所有的方法都放进EventBus中
// 而是所有带有自定义注解的方法都放进去
@Subscrible(threadMode = ThreadMode.MAIN)
public void test1(EventBean eb){
Log.d("lixm","MainActivity a ====> EventBean = " + eb);
}
@Subscrible(threadMode = ThreadMode.BACKGROUND)
public void test2(EventBean eb){
Log.d("lixm","MainActivity b ====> EventBean = " + eb);
}
// 测试,这个参数不符合,不能接收到数据
@Subscrible(threadMode = ThreadMode.MAIN)
public void test3(String str){
Log.d("lixm","MainActivity b ====> String = " + str);
}
(4)、EventBus中订阅的实现
EventBus维护一个HashMap对象,key是订阅者对象,value是订阅者对象中带有自定义注解的方法的集合。
三、事件发送
1、事件发送者调用EventBus的post方法
EventBus.getDefault().post(new EventBean(“M1”,“M2”));
2、发送方法的实现
EventBus遍历订阅者集合(hashmap),并取出每一个订阅者的方法的集合,循环执行
四、具体的代码实现
1、订阅者(兼事件发送者)activity
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.hisign.android.test.R;
public class MainActivity extends Activity {
@Override
protected void onCreate( Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event_bus_main);
EventBus.getDefault().register(this);
findViewById(R.id.btAsync).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().post(new EventBean("M1","M2"));
}
});
findViewById(R.id.btGo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
}
});
}
// MainActivity方法放到eventbus中,
// 并不是所有的方法都放进EventBus中
// 而是所有带有自定义注解的方法都放进去
@Subscrible(threadMode = ThreadMode.MAIN)
public void test1(EventBean eb){
Log.d("lixm","MainActivity a ====> EventBean = " + eb);
}
@Subscrible(threadMode = ThreadMode.BACKGROUND)
public void test2(EventBean eb){
Log.d("lixm","MainActivity b ====> EventBean = " + eb);
}
// 测试,这个参数不符合,不能接收到数据
@Subscrible(threadMode = ThreadMode.MAIN)
public void test3(String str){
Log.d("lixm","MainActivity b ====> String = " + str);
}
@Override
protected void onDestroy() {
super.onDestroy();
//EventBus.getDefault().unRegister(this);
}
}
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.hisign.android.test.R;
public class SecondActivity extends Activity {
@Override
protected void onCreate( Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event_bus_second);
EventBus.getDefault().register(this);
findViewById(R.id.btAsync).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 这里可以模拟网络加载数据(异步进行)
EventBus.getDefault().post(new EventBean("2-1","2-2"));
}
});
}
@Subscrible(threadMode=ThreadMode.MAIN)
public void a(EventBean eventBean){
// 得到数据来自异步线程,需要在主线程更新UI
Log.d("lixm","SecondActivity a ====> EventBean = " + eventBean);
}
}
2、重点:EventBus实现
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 管理类,负责将某个activity的方法添加到其中,其他的activity可以在里面寻找方法并调用
*/
public class EventBus {
/**
* 用于缓存订阅者注册进来的方法
* Object 订阅者
* List<SubscribleMethod> 订阅者的方法的集合
* SubscribleMethod 订阅者的方法的封装类
*/
private Map<Object, List<SubscribleMethod>> cacheMap;
private static EventBus instance;
private EventBus() {
cacheMap = new HashMap<>();
}
public static EventBus getDefault() {
if (instance == null) {
synchronized (EventBus.class) {
if (instance == null) {
instance = new EventBus();
}
}
}
return instance;
}
/**
* 注册,把订阅者(观察者)注册进来
* @param object 订阅者类
*/
public void register(Object object) {
// 寻找object类中,所有带有subscirble注解的方法
List<SubscribleMethod> list = cacheMap.get(object); // 判断是否订阅
Log.d("lixm", "register(),list = " + list);
if (list == null) {
list = findSubscribleMethods(object);
Log.d("lixm", "register(),findSubscribleMethods--> list = " + list.toString());
cacheMap.put(object, list);
}
}
/**
* 在指定类中查找带有自定义注解的方法
*
* @param object 观察者类
* @return
*/
private List<SubscribleMethod> findSubscribleMethods(Object object) {
List<SubscribleMethod> list = new ArrayList<>();
Class<?> clazz = object.getClass();
Log.d("lixm", "findSubscribleMethods(),clazz = " + clazz.getName());
while (clazz != null) { // 循环找,不但找自己类中的,还要找父类中的
String className = clazz.getName();
if (className.startsWith("java.") // 但如果是系统的类中,肯定没有我们自定义的注解,所以不需要解析
|| className.startsWith("javax.")
|| className.startsWith("android.")) {
break;
}
// 得到类中的所有方法
Method[] methods = clazz.getDeclaredMethods();
if (methods != null && methods.length > 0) {
for (Method method : methods) {
// 只找带有subscrible注解的方法
Subscrible subscrible = method.getAnnotation(Subscrible.class);
Log.d("lixm", "method = " + method + ", subscrible = " + subscrible);
if (subscrible == null) {
continue;
}
Class<?>[] types = method.getParameterTypes(); // 该对象表示的方法参数的类型
if (types != null) {
if (types.length != 1) {
Log.d("lixm", "only one param");
} else {
String paramName = types[0].getName();
Log.d("lixm", "paramName = " + paramName);
if(types[0].getName().equals(EventBean.class.getName())){ // 根据参数的类型来匹配,参数必须是自己指定的类型
ThreadMode threadMode = subscrible.threadMode();
SubscribleMethod subscribleMethod = new SubscribleMethod();
subscribleMethod.setMethod(method);
subscribleMethod.setSubscriber(object); // 指定订阅至
subscribleMethod.setThreadMode(threadMode);
subscribleMethod.setType(types[0]);
list.add(subscribleMethod);
}else{
Log.d("lixm", "Parameter type error.");
}
}
}
clazz = clazz.getSuperclass();
}
}
}
return list;
}
/**
* 发送数据
* cacheMap中找到当前保存的所有订阅者
* 取出每一个订阅者的方法,循环调用执行
* @param paramObj
*/
public void post(Object paramObj) {
// 直接循环cacheMap,找到相应的方法执行
if (cacheMap != null && cacheMap.size() > 0) {
Set<Object> set = cacheMap.keySet();
Iterator<Object> iterator = set.iterator(); // 订阅者的集合
Log.d("lixm", "post(),iterator = " + iterator);
while (iterator.hasNext()) {
Object object = iterator.next();
List<SubscribleMethod> list = cacheMap.get(object); // 取出每一个订阅者的方法
if (list == null || list.size() == 0) {
return;
}
for (SubscribleMethod subscribleMethod : list) { // 循环执行每一个方法
// 判断参数的类型是否一致,列表中保存的参数类型,和传进来的参数类型是否一致
if (subscribleMethod.getType().isAssignableFrom(paramObj.getClass())) {
invok(subscribleMethod, object, paramObj);
}
}
}
}
}
/**
* 方法的执行
*
* @param subscribleMethod 要执行方法的封装
* @param object 观察者(拥有方法的那个类)
* @param paramObj 要执行方法的参数(post数据的封装)
*/
private void invok(SubscribleMethod subscribleMethod, final Object object, final Object paramObj) {
final Method method = subscribleMethod.getMethod();
try {
// todo 这里需要判断方法在哪个线程执行?
if (subscribleMethod.getThreadMode() == ThreadMode.MAIN) { // 主线程执行
String mainThreadName = Thread.currentThread().getName() + "-" + Thread.currentThread().getId();
Log.d("lixm", "run in main thread,threadName = " + mainThreadName);
method.invoke(object, paramObj);
} else if (subscribleMethod.getThreadMode() == ThreadMode.BACKGROUND) { // 在子线程中执行
new Thread() {
public void run() {
try {
String subThradName = Thread.currentThread().getName() + "-" + Thread.currentThread().getId();
Log.d("lixm", "run in sub thread,subThradName = " + subThradName);
method.invoke(object, paramObj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}.start();
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* 取消注册
*
* @param object
*/
public void unRegister(Object object) {
if (object != null) {
if (cacheMap.containsKey(object)) {
cacheMap.remove(object);
}
}
}
}
3、订阅者方法的封装类
import java.lang.reflect.Method;
public class SubscribleMethod {
private Method method; // 要执行的方法
private Object subscriber; // 观察者(订阅者)
private ThreadMode threadMode; // 指定方法要执行的线程
// 方法中的参数类型
private Class<?> type;
public ThreadMode getThreadMode() {
return threadMode;
}
public void setThreadMode(ThreadMode threadMode) {
this.threadMode = threadMode;
}
public Object getSubscriber() {
return subscriber;
}
public void setSubscriber(Object subscriber) {
this.subscriber = subscriber;
}
public Class<?> getType() {
return type;
}
public void setType(Class<?> type) {
this.type = type;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
}
4、自定义注解类
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD}) // 注解用到方法上的
@Retention(RetentionPolicy.RUNTIME) // 运行时起作用
public @interface Subscrible {
ThreadMode threadMode() default ThreadMode.MAIN;
}
5、自定义参数类
public class EventBean {
private String one;
private String two;
public EventBean(String one , String two){
this.one = one;
this.two = two;
}
public String getOne() {
return one;
}
public void setOne(String one) {
this.one = one;
}
@Override
public String toString() {
return "EventBean{" +
"one='" + one + '\'' +
", two='" + two + '\'' +
'}';
}
}
public enum ThreadMode {
MAIN,
BACKGROUND
}