首发于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");        }    }}

源码