EventBus是一种用于Android的事件发布-订阅,在不相互依赖的情况下进行组件间的通信,降低耦合。
使用方式:
1.添加依赖 implementation("org.greenrobot:eventbus:3.3.1")
2.注册 EventBus.getDefault().register(this);
3.注销 EventBus.getDefault().unregister(this);
4.接收事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(Message message) {}
5.发送消息
EventBus.getDefault().post(new Message());
注意:Eventbus无法跨进程。
手写EventBus框架
流程图:
源码:
MyEventBus.java
/**
* EventBus核心类
*/
public class MyEventBus {
private static MyEventBus myEventBus;
private Map<Object, List<SubscribeMethod>> mCacheMap;
private Handler mHandler;
// 没有核心线程,只有非核心线程,并且每个非核心线程空闲等待的时间为60s,采用SynchronousQueue队列。
private ExecutorService mExecutorService;
public MyEventBus() {
mCacheMap = new HashMap<>();
mHandler = new Handler(Looper.getMainLooper());
mExecutorService = Executors.newCachedThreadPool();
}
public static MyEventBus getDefault() {
if (myEventBus == null) {
synchronized (MyEventBus.class) {
if (myEventBus == null) {
myEventBus = new MyEventBus();
}
}
}
return myEventBus;
}
// 注册
public void register(Object subscribe) {
// 获取缓存数据,判断是否已经注册
List<SubscribeMethod> subscribeMethods = mCacheMap.get(subscribe);
if (subscribeMethods != null) {
return;
}
// 未注册,遍历该类及其父类(非系统父类)所有订阅方法集合
subscribeMethods = getSubscribeMethods(subscribe);
mCacheMap.put(subscribe, subscribeMethods);
}
private List<SubscribeMethod> getSubscribeMethods(Object subscribe) {
List<SubscribeMethod> subscribeMethods = new ArrayList<>();
Class<?> aClass = subscribe.getClass();
// 遍历该类及其父类(非系统父类)所有订阅方法集合
while (aClass != null) {
// 判断该类是否是系统类
String name = aClass.getName();
if (name.startsWith("java.") || name.startsWith("javax.")
|| name.startsWith("android.") || name.startsWith("androidx.")) {
break;
}
// 获取类中的所有方法,包括私有的(private、protected、默认以及public)的方法
Method[] methods = aClass.getDeclaredMethods();
for (Method method : methods) {
// 获取方法的MySubscribe注解
MySubscribe annotation = method.getAnnotation(MySubscribe.class);
if (annotation == null) {
continue;
}
// 获取方法的参数类型,EventBus规定参数只能为一个
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length != 1) {
throw new RuntimeException("EventBus规定参数只能为一个");
}
SubscribeMethod subscribeMethod = new SubscribeMethod(method, annotation.threadMode(), parameterTypes[0]);
subscribeMethods.add(subscribeMethod);
}
// 获取父类
aClass = aClass.getSuperclass();
}
return subscribeMethods;
}
// 取消注册
public void unregister(Object subscribe) {
List<SubscribeMethod> subscribeMethods = mCacheMap.get(subscribe);
if (subscribeMethods != null) {
mCacheMap.remove(subscribe);
}
}
// 发送
public void post(Object object) {
// 遍历cacheMap中的所有注册类
Set<Object> objects = mCacheMap.keySet();
Iterator<Object> iterator = objects.iterator();
while (iterator.hasNext()) {
Object subscribe = iterator.next();
List<SubscribeMethod> subscribeMethods = mCacheMap.get(subscribe);
// 遍历注册类中的所有订阅方法
for (SubscribeMethod subscribeMethod : subscribeMethods) {
// 判断方法的参数类型跟post的参数类型是否一致
if (subscribeMethod.getEventType().isAssignableFrom(object.getClass())) {
switch (subscribeMethod.getMyThreadMode()) {
case POSTING:
case MAIN: // 接收的方法要在主线程执行
// 判断当前所在线程
if (Looper.myLooper() == Looper.getMainLooper()) {
// 当前在主线程,则直接调用
invoke(subscribeMethod, subscribe, object);
} else {
// 当前在子线程,这通过handler切换线程调用
mHandler.post(new Runnable() {
@Override
public void run() {
invoke(subscribeMethod, subscribe, object);
}
});
}
break;
case ASYNC: // 接收的方法要在子线程执行
// 判断当前所在线程
if (Looper.myLooper() == Looper.getMainLooper()) {
// 当前在主线程,则加入线程池调用
mExecutorService.execute(new Runnable() {
@Override
public void run() {
invoke(subscribeMethod, subscribe, object);
}
});
} else {
// 当前在子线程,则直接调用
invoke(subscribeMethod, subscribe, object);
}
break;
}
}
}
}
}
private void invoke(SubscribeMethod subscribeMethod, Object subscribe, Object object) {
Method method = subscribeMethod.getMethod();
try {
method.invoke(subscribe, object);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
MySubscribe.java
/**
* EventBus注解类
*/
@Target(ElementType.METHOD) // 作用域方法
@Retention(RetentionPolicy.RUNTIME) // 运行时
public @interface MySubscribe {
MyThreadMode threadMode() default MyThreadMode.POSTING;
}
MyThreadMode.java
public enum MyThreadMode {
/**
* 默认主线程
*/
POSTING,
/**
* 主线程
*/
MAIN,
/**
* 子线程
*/
ASYNC
}
SubscribeMethod.java
/**
* EventBus订阅方法类
*/
public class SubscribeMethod {
// 注册的方法
private Method method;
// 线程类型
private MyThreadMode myThreadMode;
// 参数类型
private Class<?> eventType;
public SubscribeMethod(Method method, MyThreadMode myThreadMode, Class<?> eventType) {
this.method = method;
this.myThreadMode = myThreadMode;
this.eventType = eventType;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public MyThreadMode getMyThreadMode() {
return myThreadMode;
}
public void setMyThreadMode(MyThreadMode myThreadMode) {
this.myThreadMode = myThreadMode;
}
public Class<?> getEventType() {
return eventType;
}
public void setEventType(Class<?> eventType) {
this.eventType = eventType;
}
}
使用:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyEventBus.getDefault().register(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
MyEventBus.getDefault().unregister(this);
}
@MySubscribe(threadMode = MyThreadMode.MAIN)
public void onEvent(MyEventBean myEventBean) {
Toast.makeText(MainActivity.this, myEventBean.getTitle() + " - " + myEventBean.getType(),
Toast.LENGTH_LONG).show();
}
public void click(View view) {
startActivity(new Intent(MainActivity.this, MainActivity2.class));
}
}
public class MainActivity2 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
}
public void post(View view) {
new Thread(new Runnable() {
@Override
public void run() {
MyEventBus.getDefault().post(new MyEventBean("MyEventBus", 1));
}
}).start();
}
}
个人手记,有误请指出,感谢~