共计 2772 个字符,预计需要花费 7 分钟才能阅读完成。
首发于 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");
}
}
}
源码
正文完