自写一个EventBus

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

源码

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Enaium

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值