首發於Enaium的個人博客
EventBus,什麼是EventBus。
EventBus是事件發佈-訂閱總線,簡單來說監聽一個事件,一個方法訂閱這個事件,如果事件調用,那麼訂閱了這個事件的方法也會跟着調用,這就是EventBus。
創建一個註解,用於訂閱事件,名字可以隨便起,當然也可以叫Subscribe,我這裏叫Event。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Event {
}
創建Listener監聽器。
public class Listener {
}
創建MethodBean類,來儲存訂閱方法,Object是訂閱類的對象,Method就是被訂閱的方法。
public class MethodBean {
private final Object object;
private final Method method;
public MethodBean(Object object, Method method) {
this.object = object;
this.method = method;
}
public Object getObject() {
return object;
}
public Method getMethod() {
return method;
}
}
創建一個EventManager,來管理訂閱的事件。
public class EventManager {
}
創建一個HashMap合集K是監聽器,V是被調用的方法,因爲一個監聽器可能有多個方法,並且要保證線程安全,需要使用CopyOnWriteArrayList。
public class EventManager {
private final HashMap<Class<? extends Listener>, CopyOnWriteArrayList<MethodBean>> events = new HashMap<>();
}
創建register和unregister方法來註冊和取消註冊訂閱的對象。
public class EventManager {
public void register(Object o) {
}
public void unregister(Object o) {
}
}
註冊。
public void register(Object o) {
Class<?> type = o.getClass();//獲取類。
for (Method method : type.getDeclaredMethods()) {//遍歷出所有方法。
if (method.getParameterTypes().length == 1 && method.isAnnotationPresent(Event.class)) {//保證方法只有一個參數,並且有Event這個註解。
method.setAccessible(true);
@SuppressWarnings("unchecked")
Class<? extends Listener> listener = (Class<? extends Listener>) method.getParameterTypes()[0];
MethodBean methodBean = new MethodBean(o, method);
//把這些都put到events裏面。
if (events.containsKey(listener)) {
if (!events.get(listener).contains(methodBean)) {
events.get(listener).add(methodBean);
}
} else {
events.put(listener, new CopyOnWriteArrayList<>(Collections.singletonList(methodBean)));
}
}
}
}
取消註冊很簡單,只要將events的K和V移除就行。
public void unregister(Object o) {
events.values().forEach(methodBeans -> methodBeans.removeIf(methodMethodBean -> methodMethodBean.getObject().equals(o)));
events.entrySet().removeIf(event -> event.getValue().isEmpty());
}
創建一個getEvent方法來獲取一個監聽器的所有訂閱。
public CopyOnWriteArrayList<MethodBean> getEvent(Class<? extends Listener> type) {
return events.get(type);
}
創建一個單例。
public enum Main {
INSTANCE;
EventManager eventManager = new EventManager();
}
回到剛纔創建的Listener類。
創建一個call方法來進行事件觸發操作,當事件觸發,獲取監聽器的所有訂閱方法來調用,參數就是當前的監聽器。
public class Listener {
public void call() {
CopyOnWriteArrayList<MethodBean> methodBeans = Main.INSTANCE.eventManager.getEvent(this.getClass());
if(methodBeans == null) {
return;
}
methodBeans.forEach(event -> {
try {
event.getMethod().invoke(event.getObject(), this);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
});
}
}
創建一個監聽器。
public class UpdateEvent extends Listener {
}
一個簡單的EventBus已經寫好了,現在來測試一下。
public enum Main {
INSTANCE;
EventManager eventManager = new EventManager();
public static void main(String[] args) {
Main.INSTANCE.eventManager.register(new Test());//register
new UpdateEvent().call();
}
static class Test {
@Event
public void on(UpdateEvent e) {
System.out.println("Event trigger");
}
}
}