EventBus分析源码

1.EventBus的注册就从这里开始。

public static EventBus getDefault() {
    if (defaultInstance == null) {
        synchronized (EventBus.class) {
            if (defaultInstance == null) {
                defaultInstance = new EventBus();
            }
        }
    }
    return defaultInstance;
}

这是一个经典的单例双重锁,结构  也就是说 , 整个eventbus在项目中是以

单例的形式出现的

2.EventBus.register(Object subscriber)

这里是注册订阅者的地方,同样的注册方式有这么:

  • register(Object subscriber)
  • register(Object subscriber, int priority)
  • registerSticky(Object subscriber)
  • registerSticky(Object subscriber, int priority)

它们之间最主要的区别就是参数的不同。在实现上它们都是调用void register(Object subscriber, boolean sticky, int priority)函数实现的。

public void register(Object subscriber) {
    Class<?> subscriberClass = subscriber.getClass();
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}

首先是调用了这样的一个方法 findSubscriberMethods()

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
    if (subscriberMethods != null) {
        return subscriberMethods;
    }

如果已经订阅也就是注册了就直亅接返回一个订阅的  方法的集合  subscriberMethods

subscribe

这个方法的参数呢就是一个订阅者subscriber     一个是 订阅者的类型 subscriberMethod

回去后一个for循环遍历所有的方法这时候呢这么就知道这个方法是接受的方法呢就是一个标识   @Subscribe注解

@Subscribe
public void ss(String str){

    Log.d("TAG",str);

}

EventBus.getDefault().postSticky("Ss");

发送的一个黏性事件

public void postSticky(Object event) {
    synchronized (stickyEvents) {
        stickyEvents.put(event.getClass(), event);
    }
  
    post(event);

这里呢主要是做一个记录 就是讲黏性事件记录在一个集合里在接受的时候会做判断事件的类型

但是最终都会走这个post方法

几个标红的方法  post不管是黏性还是普通都会走这个方法 

eventQueue他是一个事件的队列的集合

postingState.canceled  这个呢是做了一个是否已经拦截的处理   eventbus有一个拦截的方法

postSingleEvent  我们进去看他做了什么

postSingleEvent这个方法  你看他的参数  postingState看这个  一个looper轮询器   进去后呢

public void post(Object event) {
    // 通过工厂类,获取一个执行状态类
    // 每一个线程对应一个
    PostingThreadState postingState = currentPostingThreadState.get();
    // 把Event加入到队列中
    List<Object> eventQueue = postingState.eventQueue;
    eventQueue.add(event);

    // 如果这个信息类并没有在执行
    if (!postingState.isPosting) {
        // 是否是主线程
        postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
        // 改变执行状态
        postingState.isPosting = true;
        // 判断执行是否被取消了
        if (postingState.canceled) {
            throw new EventBusException("Internal error. Abort state was not reset");
        }
        // 开始循环发送Event
        try {
            while (!eventQueue.isEmpty()) {
                // 别忘了ArrayList的remove会返回remove的对象
                // 执行队列中第一个Event
                postSingleEvent(eventQueue.remove(0), postingState);
            }
        } finally {
            // 执行结束之后,要重置状态类的属性
            postingState.isPosting = false;
            postingState.isMainThread = false;
        }
    }
}

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
    // 得到Event的Class
    Class<?> eventClass = event.getClass();
    boolean subscriptionFound = false;
    // 如果Event是支持继承的
    if (eventInheritance) {
        // 找到使用Event的父类
        List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
        int countTypes = eventTypes.size();
        for (int h = 0; h < countTypes; h++) {
            Class<?> clazz = eventTypes.get(h);
            // 开始发送Event给当前的Class
            // 每一次都要跟下一次的结果进行 或操作,也就是只要有一个Class的Event没找到,都会返回false
            subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
        }
    } else {
        // 开始发送Event给当前的Class
        subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
    }
    //如果并没有找到这个Event绑定的信息
    if (!subscriptionFound) {
        // 是否打印log
        if (logNoSubscriberMessages) {
            Log.d(TAG, "No subscribers registered for event " + eventClass);
        }
        // 是否发送Event
        if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                eventClass != SubscriberExceptionEvent.class) {
            post(new NoSubscriberEvent(this, event));
        }
    }
}

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
    CopyOnWriteArrayList<Subscription> subscriptions;
    synchronized (this) {
        // 得到和Event对应的类和方法
        subscriptions = subscriptionsByEventType.get(eventClass);
    }
    // 判空
    if (subscriptions != null && !subscriptions.isEmpty()) {
        // 对列表循环
        for (Subscription subscription : subscriptions) {
            // 设置要执行的信息
            postingState.event = event;
            postingState.subscription = subscription;
            boolean aborted = false;
            try {
                // 执行Class中被注解的方法
                postToSubscription(subscription, event, postingState.isMainThread);
                // 如果post被取消了,停止循环
                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 {
                // 通过Handler机制,在主线程中调用被注解的方法
                mainThreadPoster.enqueue(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);
    }
}

取出订阅方法的线程模式,之后根据线程模式来分别处理。举个例子,如果线程模式是MAIN,提交事件的线程是主线程的话则通过反射,直接运行订阅的方法,如果不是主线程,我们需要mainThreadPoster将我们的订阅事件入队列,mainThreadPoster是HandlerPoster类型的继承自Handler,通过Handler将订阅方法切换到主线程执行。

EventBus.getDefault().unregister(this);

注销呢逻辑也很简单就是遍历订阅的集合 然后把我们传进去的订阅  也就是这个this   从集合删除

public synchronized void unregister(Object subscriber) {
    List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
    if (subscribedTypes != null) {
        for (Class<?> eventType : subscribedTypes) {
            unsubscribeByEventType(subscriber, eventType);
        }
        typesBySubscriber.remove(subscriber);
    } else {
        Log.w(TAG, "注册的注册人之前没有注册: " + subscriber.getClass());
    }
}

builder

EventBus.b

为什么要调用 builder    

我们不可以直接new一个出来吗,看源码
原来EventBusBuilder的构造函数不是public的。。。。但是EventBusBuilder有个方法可以得到EventBus实例

ublic EventBus installDefaultEventBus() {
    synchronized (EventBus.class) {
        if (EventBus.defaultInstance != null) {
            throw new EventBusException("Default instance already exists." +
                    " It may be only set once before it's used the first time to ensure consistent behavior.");
        }
        EventBus.defaultInstance = build();
        return EventBus.defaultInstance;
    }
}

EventBus e   = EventBus.builder()
              .eventInheritance(true)
              .ignoreGeneratedIndex(true)
              .installDefaultEventBus();

EventBus 我们一般在使用 EventBus 的时候,都会使用EventBus.getDefault( ) 方法来获取一个 EventBus 单例,这个单例是静态的,全局可访问的。上面的代码我们在获取 EventBus 单例后调用 register 方法,将 EventBusActivity 注册到 EventBus 中,这个时候 EventBus 就会持有 Activity 的引用,由于单例是静态的,生命周期和整个 App 生命周期 一致,如果我们不调用 unRegister 方法的话

EventBusActivity 实例就会泄漏


 

面试总结

线程通信的一种

EventBus采用的是观察者模式,

一个黏性事件,和普通事件,发布者,和订阅者‘’

接收方法有一定的限制,首先方法必须是Public

数的类型必须是我们定义的事件类,比如说我们发送了一个String类型的

接受的时候也要是一个String类型的对吧

而且方法必须添加”

@Subscribe“注解,因为在EventBus内部查找方法时,是根据注解来进行区分;

猜你喜欢

转载自blog.csdn.net/zzf0521/article/details/82834270