最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 自写一个EventBus

    正文概述 掘金(Enaium)   2021-02-25   568

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

    源码


    起源地下载网 » 自写一个EventBus

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元