事件传递EventBus

目录

概念

EventBus:是一个Android事件发布/订阅框架,通过解耦发布者与订阅者的方式,大大的简化了Activity与Activity,Activity与Fragment,Fragment与Fragment等之间的数据传递,从而使得代码更简洁明了。

使用

1,配置

  • 打开App的build.gradle,在dependencies中添加最新的EventBus依赖:
    3.0以下版本的AndroidStudio : compile 'org.greenrobot:eventbus:3.1.1'
    3.0及以上版本的AndroidStudio : implementation 'org.greenrobot:eventbus:3.1.1'>
  • 索引加速模式(在AndroidStudio3.1.3上配置成功,在2.2.2版本上使用网上的两种方案均无MyEventBusIndex文件生成) 。成功配置的步骤如下(针对AndroidStudio3.1.3)
1,在app的build.gradle文件的dependencies中添加:
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.0.1'
2,在app的build.gradle文件的defaultConfig中添加:(com.learn.study:当前的包名,可以自己配置)
javaCompileOptions {
    annotationProcessorOptions {
        arguments = [ eventBusIndex : 'com.learn.study.MyEventBusIndex' ]
    }
}
3,rebuiid项目后在app的build/generated/source/apt/debug中找到:MyEventBusIndex文件

2,注册与注销

//注册(一般在Activity或Fragment的onCreate中进行)
if (!EventBus.getDefault().isRegistered(this)) {
    EventBus.getDefault().register(this);
}
//注销(一般是在Activity或Fragment的onDestory中进行)
if (EventBus.getDefault().isRegistered(this)) {
    EventBus.getDefault().unregister(this);
}

//补充(如果使用了索引加速):在Application中配置:
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();

3,接收事件

//3.0以后方法名可以任意,但必须加上@Subscribe的标识,同时设置参数为:
threadMode:当前接收事件的执行线程
sticky:是否接收粘性事件;
priority:设置优先级
方法的参数与发送的数据类型一致,必须为对象类型,如:必须使用Integer而不能使用int
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true, priority = 0)
public void getMainData(Integer number) {
    Log.d(TAG, "ThreadMode : getMainData: " + number + " ;; " + Thread.currentThread().getName());
}

四种线程模型(ThreadMode:定义线程类型的枚举类)说明:

  • POSTING : 在当前发送的线程中执行(不用切换线程,最轻量级)
  • MAIN:在主线程中执行
  • MAIN_ORDERED:在主线程中执行,但事件始终排队等候确保调用为非阻塞(不常用)
  • BACKGROUND:后台线程,当在UI线程时中发布时才会新建一个后台线程执行
  • ASYNC:交给线程池来管理,直接通过asyncPoster调度。

4,发送事件

//发送普通事件
EventBus.getDefault().post(10);
//发送粘性事件
EventBus.getDefault().postSticky(20);

5,注意事项

1,有注册必须有注销,保证一一对应,同时调用的生命周期方法也对应
2,注册页面必须有接收方法,主要是需要识别到有Subscribe的注解,发送界面不需要注册。
3,同一个事件可以定义多个接收,参数必须是对象类型。如:发送的是int但接收参数必须为Interger
4,使用普通的post发送事件时,必须先注册才能收到。而postSticky可以在发送后注册也能收到

//1,验证普通事件与粘性事件的发送与注册顺序
private void testEventBus() {
    EventBus.getDefault().postSticky(20);
    if (!EventBus.getDefault().isRegistered(this)) {
        EventBus.getDefault().register(this);
    }
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true, priority = 0)
public void getMainData(Integer number) {
    Log.d(TAG, "ThreadMode : getMainData: " + number + " ;; " + Thread.currentThread().getName());
}
//打印结果:(即事件能够收到并处理)
10-24 21:13:52.574 5913-5913/com.learn.study D/MainActivity: ThreadMode : getMainData: 20 ;; main

private void testEventBus() {
    EventBus.getDefault().post(10);
    if (!EventBus.getDefault().isRegistered(this)) {
        EventBus.getDefault().register(this);
    }
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true, priority = 0)
public void getMainData(Integer number) {
    Log.d(TAG, "ThreadMode : getMainData: " + number + " ;; " + Thread.currentThread().getName());
}
//无打印,即事件未接收

//2,验证线程模型
@Subscribe(threadMode = ThreadMode.MAIN)
public void getMainData(Integer number) {
    Log.d(TAG, "ThreadMode : getMainData: " + number + " ;; " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void getThreadData(Integer number) {
    Log.d(TAG, "ThreadMode : getThreadData: " + number + " ;; " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.POSTING)
public void getPostData(Integer number) {
    Log.d(TAG, "ThreadMode : getPostData: " + number + " ;; " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void getAsyncData(Integer number) {
    Log.d(TAG, "ThreadMode : getAsyncData: " + number + " ;; " + Thread.currentThread().getName());
}
EventBus.getDefault().post(10);
Log.d("MainActivity", "ThreadMode : sendData :" + Thread.currentThread().getName());
//在主线程中发送结果打印:
10-24 21:28:19.490 6837-6837/com.learn.study D/MainActivity: ThreadMode : getMainData: 10 ;; main
    ThreadMode : getPostData: 10 ;; main
10-24 21:28:19.491 6837-7309/com.learn.study D/MainActivity: ThreadMode : getThreadData: 10 ;; pool-1-thread-1
10-24 21:28:19.491 6837-6837/com.learn.study D/MainActivity: ThreadMode : sendData :main
10-24 21:28:19.491 6837-7310/com.learn.study D/MainActivity: ThreadMode : getAsyncData: 10 ;; pool-1-thread-2

//在子线程中发送结果打印:
10-24 21:33:22.969 7800-7859/com.learn.study D/MainActivity: ThreadMode : getThreadData: 10 ;; Thread-4
    ThreadMode : getPostData: 10 ;; Thread-4
10-24 21:33:22.970 7800-7860/com.learn.study D/MainActivity: ThreadMode : getAsyncData: 10 ;; pool-1-thread-1
10-24 21:33:22.970 7800-7859/com.learn.study D/MainActivity: ThreadMode : sendData :Thread-4
10-24 21:33:23.028 7800-7800/com.learn.study D/MainActivity: ThreadMode : getMainData: 10 ;; main

//3,验证接收事件的优先级(相同的线程中才存在优先级问题,同时拦截才有效果)
10-24 22:04:43.762 10532-10596/com.learn.study D/MainActivity: ThreadMode : getThreadData: 10 ;; Thread-4;; 优先级:6
    ThreadMode : getPostData: 10 ;; Thread-4;; 优先级:3
10-24 22:04:43.763 10532-10596/com.learn.study D/MainActivity: ThreadMode : sendData :Thread-4
10-24 22:04:43.763 10532-10597/com.learn.study D/MainActivity: ThreadMode : getAsyncData: 10 ;; pool-1-thread-1;; 优先级:0
10-24 22:04:43.810 10532-10532/com.learn.study D/MainActivity: ThreadMode : getMainData: 10 ;; main;; 优先级:10
    ThreadMode : getMain1Data: 10 ;; main;; 优先级:7

原理(针对3.1.1版本的源码)

1,注册的流程

//1,使用双重校验的单例创建对象:EventBus.getDefault()
public static EventBus getDefault() {
    if (defaultInstance == null) {
        synchronized (EventBus.class) {
            if (defaultInstance == null) {
                defaultInstance = new EventBus();
            }
        }
    }
    return defaultInstance;
}
//2,register()调用注册的方法
public void register(Object subscriber) {
    Class subscriberClass = subscriber.getClass();
    //查找当前注册类所有的接收方法
    List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}
//具体实现查找接收方法:
List findSubscriberMethods(Class subscriberClass) {
    //1,从Map集合METHOD_CACHE(键:注册的类class对象,值:当前注册类里面的接收方法)中查找方法,如果查询到方法则直接返回方法集合List,否则重新获取
    List subscriberMethods = METHOD_CACHE.get(subscriberClass);
    if (subscriberMethods != null) {
        return subscriberMethods;
    }
    if (ignoreGeneratedIndex) {
        //2,忽视索引加速的方式,直接使用反射的方式获取的注册类下的所有接受方法:最后还是调用findUsingReflectionInSingleClass()方法
        subscriberMethods = findUsingReflection(subscriberClass);
    } else {
        //3,获取到注册类里面的接收方法
        subscriberMethods = findUsingInfo(subscriberClass);
    }
    if (subscriberMethods.isEmpty()) {
        throw new EventBusException("Subscriber " + subscriberClass
                    + " and its super classes have no public methods with the @Subscribe annotation");
    } else {
        METHOD_CACHE.put(subscriberClass, subscriberMethods);
        return subscriberMethods;
    }
}

private List findUsingInfo(Class subscriberClass) {
    //1,这里存在一个查找状态池:FIND_STATE_POOL,大小为4,减少对象的创建。
    FindState findState = prepareFindState();
    findState.initForSubscriber(subscriberClass);
    while (findState.clazz != null) {
        //2,查找注册类的接受方法,如果添加了索引加速,而返回接受方法,否则返回null
        findState.subscriberInfo = getSubscriberInfo(findState);
        if (findState.subscriberInfo != null) {
            SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
            for (SubscriberMethod subscriberMethod : array) {
                if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                    findState.subscriberMethods.add(subscriberMethod);
                }
            }
        } else {
            //未添加索引加速时使用反射获取接受方法
            findUsingReflectionInSingleClass(findState);
        }
        findState.moveToSuperclass();
    }
    return getMethodsAndRelease(findState);
}
//使用索引加速获取方法
private SubscriberInfo getSubscriberInfo(FindState findState) {
        if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
            SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
            if (findState.clazz == superclassInfo.getSubscriberClass()) {
                return superclassInfo;
            }
        }
        if (subscriberInfoIndexes != null) {
            for (SubscriberInfoIndex index : subscriberInfoIndexes) {
                SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
                if (info != null) {
                    //使用了索引加速则info返回索引的接收方法,否则返回null
                    return info;
                }
            }
        }
        return null;
    }

//使用反射获取接收方法
private void findUsingReflectionInSingleClass(FindState findState) {
        Method[] methods;
        try {
            //1,使用反射先获取到注册类里面的所有方法
            methods = findState.clazz.getDeclaredMethods();
        } catch (Throwable th) {
            // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
            methods = findState.clazz.getMethods();
            findState.skipSuperClasses = true;
        }
        //2,遍历所有方法,找到接收事件的方法
        for (Method method : methods) {
            int modifiers = method.getModifiers();
            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                Class[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length == 1) {
                    //3,通过获取方法上的注解Subscribe来区分接收事件的方法.
                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                    if (subscribeAnnotation != null) {
                        Class eventType = parameterTypes[0];
                        if (findState.checkAdd(method, eventType)) {
                            ThreadMode threadMode = subscribeAnnotation.threadMode();
                            //4,将接收事件的方法信息添加到查询状态的对象中
                            findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                    subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                        }
                    }
                } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                    String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                    throw new EventBusException("@Subscribe method " + methodName +
                            "must have exactly 1 parameter but has " + parameterTypes.length);
                }
            } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                throw new EventBusException(methodName +
                        " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
            }
        }
    }

//查找完成接收事件的方法后,调用subscribe(),将注册类,接收方法,接收事件的类型等添加到对应的Map集合中进行保存,避免相应信息每次获取
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions == null) {
            subscriptions = new CopyOnWriteArrayList<>();
            subscriptionsByEventType.put(eventType, subscriptions);
        } else {
            if (subscriptions.contains(newSubscription)) {
                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                        + eventType);
            }
        }

        int size = subscriptions.size();
        //根据接收事件的优先级,将订阅事件存放到subscriptionsByEventType集合中
        for (int i = 0; i <= size; i++) {
            if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
                subscriptions.add(i, newSubscription);
                break;
            }
        }

        List> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);
        //这里用来处理粘性事件
        if (subscriberMethod.sticky) {
            if (eventInheritance) {
                // Existing sticky events of all subclasses of eventType have to be considered.
                // Note: Iterating over all events may be inefficient with lots of sticky events,
                // thus data structure should be changed to allow a more efficient lookup
                // (e.g. an additional map storing sub classes of super classes: Class -> List).
                Set, Object>> entries = stickyEvents.entrySet();
                for (Map.Entry, Object> entry : entries) {
                    Class candidateEventType = entry.getKey();
                    if (eventType.isAssignableFrom(candidateEventType)) {
                        Object stickyEvent = entry.getValue();
                         //后续调用跟普通事件相同的流程.
                        checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                    }
                }
            } else {
                Object stickyEvent = stickyEvents.get(eventType);
                checkPostStickyEventToSubscription(newSubscription, stickyEvent);
            }
        }
    }

2,注销流程

EventBus.getDefault().unregister(this);
//1,与注册相同,使用单例获取到EventBus对象.
public synchronized void unregister(Object subscriber) {
        //typesBySubscriber这是一个Map集合,键为:注册的类,值为当前类中处理的事件类型集合
        List> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class eventType : subscribedTypes) {
                unsubscribeByEventType(subscriber, eventType);
            }
            //从存放注册类与事件类型的对照集合中移除注册类,这样也可以防止对象引用无法释放.
            typesBySubscriber.remove(subscriber);
        } else {
            logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }

private void unsubscribeByEventType(Object subscriber, Class eventType) {
        //subscriptionsByEventType这也是一个Map集合,键:事件类型,值:事件类型对应的接收方法.
        //Subscription:将注册类与接收方法封装为了一个数据结构
        List subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions != null) {
            int size = subscriptions.size();
            for (int i = 0; i < size; i++) {
                Subscription subscription = subscriptions.get(i);
                if (subscription.subscriber == subscriber) {
                    subscription.active = false;
                    //移除事件类型对应的方法
                    subscriptions.remove(i);
                    i--;
                    size--;
                }
            }
        }
    }

3,发布事件

//发送粘性事件
public void postSticky(Object event) {
        synchronized (stickyEvents) {
            //将粘性事件存入stickyEvents集合中,键为:事件类型,值:事件的具体值
            stickyEvents.put(event.getClass(), event);
        }
        // Should be posted after it is putted, in case the subscriber wants to remove immediately
        post(event);
    }

//发送普通事件
public void post(Object event) {
        //使用ThreadLocal存放当前线程状态对象:PostingThreadState
        PostingThreadState postingState = currentPostingThreadState.get();
        List eventQueue = postingState.eventQueue;
        //1,将事件加入到事件集合中
        eventQueue.add(event);
        if (!postingState.isPosting) {
            postingState.isMainThread = isMainThread();
            postingState.isPosting = true;
            if (postingState.canceled) {
                throw new EventBusException("Internal error. Abort state was not reset");
            }
            try {
                while (!eventQueue.isEmpty()) {
                   //2,事件处理的方法
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        //3,获取事件类型的class对象,如:int 10 ,最终获取的是:java.lang.Integer
        Class eventClass = event.getClass();
        boolean subscriptionFound = false;
        if (eventInheritance) {
            List> eventTypes = lookupAllEventTypes(eventClass);
            int countTypes = eventTypes.size();
            for (int h = 0; h < countTypes; h++) {
                Class clazz = eventTypes.get(h);
                //4,发布事件调用方法:postSingleEventForEventType()
                subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
            }
        } else {
            subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
        }
        if (!subscriptionFound) {
            if (logNoSubscriberMessages) {
                logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
            }
            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                    eventClass != SubscriberExceptionEvent.class) {
                post(new NoSubscriberEvent(this, event));
            }
        }
    }

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class eventClass) {
        CopyOnWriteArrayList subscriptions;
        synchronized (this) {
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            for (Subscription subscription : subscriptions) {
                postingState.event = event;
                postingState.subscription = subscription;
                boolean aborted = false;
                try {
                    //5,根据不同的线程模型来处理发布的事件
                    postToSubscription(subscription, event, postingState.isMainThread);
                    aborted = postingState.canceled;
                } finally {
                    postingState.event = null;
                    postingState.subscription = null;
                    postingState.canceled = false;
                }
                if (aborted) {
                    break;
                }
            }
            return true;
        }
        return false;
    }

    //根据接收处理事件的线程模型不同,分别在对应的线程中处理事件.
    private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch (subscription.subscriberMethod.threadMode) {
            case POSTING:            //在当前发布的线程中处理
                invokeSubscriber(subscription, event);
                break;
            case MAIN:                 //在主线程中处理事件
                if (isMainThread) {
                    invokeSubscriber(subscription, event);
                } else {
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            case MAIN_ORDERED:
                if (mainThreadPoster != null) {
                    mainThreadPoster.enqueue(subscription, event);
                } else {
                    // temporary: technically not correct as poster not decoupled from subscriber
                    invokeSubscriber(subscription, event);
                }
                break;
            case BACKGROUND:
                if (isMainThread) {
                    backgroundPoster.enqueue(subscription, event);
                } else {
                    invokeSubscriber(subscription, event);
                }
                break;
            case ASYNC:
                asyncPoster.enqueue(subscription, event);
                break;
            default:
                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
        }
    }

void invokeSubscriber(Subscription subscription, Object event) {
        try {
            //6,最终调用method的invoke方法来处理
            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
        } catch (InvocationTargetException e) {
            handleSubscriberException(subscription, event, e.getCause());
        } catch (IllegalAccessException e) {
            throw new IllegalStateException("Unexpected exception", e);
        }
    }
 
 

4,索引加速的原理

在编译期生成类用来记录所有的接收事件方法,将运行期的反射提前到编译期,避免了运行期使用反射增加的性能开销。编译期生成的类如下:

public class MyEventBusIndex implements SubscriberInfoIndex {
    //用来存放所有的接收事件方法,避免后面需要通过反射获取,减小运行的性能开销
    private static final Map, SubscriberInfo> SUBSCRIBER_INDEX;

    static {
        SUBSCRIBER_INDEX = new HashMap, SubscriberInfo>();
        putIndex(new SimpleSubscriberInfo(MainActivity.class, true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("getMainData", Integer.class, ThreadMode.MAIN, 10, false),
            new SubscriberMethodInfo("getMain2Data", Integer.class, ThreadMode.MAIN, 7, false),
            new SubscriberMethodInfo("getThreadData", Integer.class, ThreadMode.BACKGROUND, 6, false),
            new SubscriberMethodInfo("getPostData", Integer.class, ThreadMode.POSTING, 3, false),
            new SubscriberMethodInfo("getAsyncData", Integer.class, ThreadMode.ASYNC),
        }));

    }

    private static void putIndex(SubscriberInfo info) {
        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
    }

    @Override
    public SubscriberInfo getSubscriberInfo(Class subscriberClass) {
        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
        if (info != null) {
            return info;
        } else {
            return null;
        }
    }
}

参考:

https://www.cnblogs.com/bugly/p/5475034.html

你可能感兴趣的:(事件传递EventBus)