首页 > 其他 > 详细

EventBus

时间:2020-04-05 22:51:23      阅读:71      评论:0      收藏:0      [点我收藏+]

申明:低级码农问题解决中的参考和解决后的小结,仅用于个人记录,能力有限,可能有些错误,缺陷不自知,欢迎在评论中指正,谢谢!

参考:

EventBus的介绍部分参考:https://www.jianshu.com/p/e7d5c7bda783

DIY一个EventBus,熟悉ThreadMode.MAIN模式下的订阅、发布流程,参考的网易云课堂官方、彭锡老师主讲的公开课,但原课程已下架。

 

1、EventBus 简介

  EventBus是一种用于Android的事件发布-订阅总线,由GreenRobot开发,它简化了应用程序内各个组件之间进行通信的复杂度,尤其是碎片之间进行通信的问题,可以避免由于使用广播通信而带来的诸多不便。

  EventBus有四种线程模式,posting、main、backgroud、async,他们的意义如下:
  一、POSTING:默认,表示事件处理函数的线程跟发布事件的线程在同一个线程。
  二、MAIN:表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
  三、BACKGROUND:表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
  四、ASYNC:表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。

  下面我们通过一个简单的例子来熟悉Event Bus的使用
  一、添加依赖,略;
  二、订阅者注册和添加接收事件的方法,在接收事件方法中对事件进行处理。EventBus 3.0之后,被Subscribe注解的方法即是事件的接收方法。

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        EventBus.getDefault().register(this);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void subscribe(String s) {
        tv.setText(s);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }

  三、发布者发布事件

EventBus.getDefault().post("eventbus_2");

 

DIY一个EventBus

  通过自己写一个EventBus来熟悉流程。这个EventBus很简单,只有一种线程模式:main,不支持黏性事件和优先级,判断过程也及其简单。

一、创建线程模式

public enum ThreadMode {
    POSTING,
    MAIN,
}

二、创建注解

  EventBus 3.0以上,通过注解标识事件的接收方法。注解有ThreadMode/线程模式、sticky/粘性、property/消息等级等参数,我们这里只关注ThreadMode。注意@Retention(RetentionPolicy.RUNTIME)。

// 此注解至作用于方法
@Target(ElementType.METHOD)
// *,表示jvm加载class文件后,注解依然存在。没有这个对注解(Subscribe)的注解,后面获取注解将返回null
@Retention(RetentionPolicy.RUNTIME)
public @interface Subscribe {
    ThreadMode threadMode() default ThreadMode.POSTING;
}

三、封装接收方法类

  对订阅者的事件接收方法进行封装。我们可以看一下接收方法,有哪些重要的信息,把这些信息抽象出来即可。1、方法本身;2、标识此方法是事件接收方法的注解,这个注解的参数是ThreadMode(黏性、优先级忽略);3、接收方法的参数:事件类型。所以事件的接收方法类,就是这三个成员变量及Getter、Setter,还有就是构造方法。

public class SubscribeMethod {
    // 线程模式
    ThreadMode threadMode;
    // 事件的接收方法本身
    Method method;
    // 事件的接收方法的参数,事件类型
    Class eventType;

    /** 构造方法和Setter、Getter略 */
}

四、创建自己得EventBus

  前面只是构造对象类的话,这个就是EventBus的核心了:订阅者注册和发布者发布事件。注意:EventBus必须是单例。

  1、注册过程。注册过程是把订阅者(main模式的Activity)和事件的接收方法以键值对形式缓存起来。核心是找到事件的接收方法,一个重要的特征是被Subscribe注解了,然后可以在根据参数、返回值,还有其他条件,进一步判断。

  注意:tempMethod.getAnnotation(Subscribe.class),Subscribe必须被@Retention(RetentionPolicy.RUNTIME)注解,否则这个方法返回null。

    HashMap<Object, ArrayList<SubscribeMethod>> methodMap = new HashMap<>();

    // 找到哪些方法(用于接收)
    public void register(Object subscriber) {
        // 接收事件的方法(可能不止一个)
        ArrayList<SubscribeMethod> methods = methodMap.get(subscriber);
        if (methods == null) {
            methods = findEventReceiverMethod(subscriber);
            methodMap.put(subscriber, methods);
        }
    }

    private ArrayList<SubscribeMethod> findEventReceiverMethod(Object obj) {
        ArrayList<SubscribeMethod> methods = new ArrayList<>();
        Class clz = obj.getClass();
        // 获取当前类的方法,getMethods()获取当前类和父类的方法
        Method[] methodArray = clz.getDeclaredMethods(); // 当前类的方法
        for (Method tempMethod : methodArray) {
            Subscribe subscribe = tempMethod.getAnnotation(Subscribe.class);
            // 过滤注解
            if (subscribe == null) {
                continue;
            }
            // EventBus must return null
            Type returnType = tempMethod.getGenericReturnType();
            // EventBus must has only one param
            Class[] paramTypes = tempMethod.getParameterTypes();
            SubscribeMethod tempSubscribeMethod = new SubscribeMethod();
            tempSubscribeMethod.setEventType(paramTypes[0]);
            // 这里可以根据不同的线程模式
            tempSubscribeMethod.setThreadMode(subscribe.threadMode());
            tempSubscribeMethod.setMethod(tempMethod);
            methods.add(tempSubscribeMethod);
        }
        return methods;
    }

  2、发布者发布,通过反射的方式调用订阅者的事件接收方法。

  标准情况下,这里会判断线程模式,来确定在哪个线程,回调执行事件的接收方法。

    public void post(Object event) {
        Set<Object> keySet = methodMap.keySet();
        for (Object key : keySet) {
            ArrayList<SubscribeMethod> methodLs = methodMap.get(key);
            for (SubscribeMethod subscribeMethod : methodLs) {
                // 不要所有的都接受,通过判断发布事件
                if (subscribeMethod.getEventType().isAssignableFrom(event.getClass())) {
                    try {
                        subscribeMethod.getMethod().invoke(key, event);
                    } catch (Exception e) {
                        e.toString();
                    }
                }
            }
        }
    }

 

EventBus

原文:https://www.cnblogs.com/hellodingc/p/12639570.html

(1)
(1)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!