EventBus 普通事件的post

EventBus 普通事件的post

当订阅事件完成后,就需要发送时间通知了,调用比较简单

EventBus.getDefault().post(eventType);

看一下post事件:

/** Posts the given event to the event bus. */
    public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> eventQueue = postingState.eventQueue;
        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()) {
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }

首先出现了一个currentPostingThreadState,他是干啥的?

private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
        @Override
        protected PostingThreadState initialValue() {
            return new PostingThreadState();
        }
    };

他是一个ThreadLocal,这个是干啥的?当有多线程进行操作的时候,有的资源可以保存在线程本地使用,免争抢排队;叫他线程本地变量;

引用一句话:Java并发编程:深入剖析ThreadLocal

ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。

初始化的时候创建了一个PostingThreadState对象,点进去看一下,发现他是EventBus的一个静态内部类,还是final类型的;

/** For ThreadLocal, much faster to set (and get multiple values). */
    final static class PostingThreadState {
        final List<Object> eventQueue = new ArrayList<>();
        boolean isPosting;
        boolean isMainThread;
        Subscription subscription;
        Object event;
        boolean canceled;
    }

看看注释:供线程本地变量使用,使之更快set/get;由此知道,就一中间产物,用于事件发送时记录操作过程中的某些状态的;

因为post可以在跨线程操作,所以存在这么一个东西;

回到代码中,先取得线程本地变量的对象;将参数添加到发送状态的List集合中;

postingState.isPosting

默认是false,所以直接进入if中;他相当于一个开关,进去之后立马将状态改为true,发送完成或者失败后才置false;

postingState.isMainThread = isMainThread();

判断当前是否是主线程;

往里追一下代码:

private boolean isMainThread() {
    return mainThreadSupport != null ? mainThreadSupport.isMainThread() : true;
}
// @Nullable
private final MainThreadSupport mainThreadSupport;
private boolean isMainThread() {
    return mainThreadSupport != null ? mainThreadSupport.isMainThread() : true;
}

EventBus初始化的时候默认调用了EventBusBuilder中的getMainThreadSupport:

MainThreadSupport getMainThreadSupport() {
        if (mainThreadSupport != null) {
            return mainThreadSupport;
        } else if (Logger.AndroidLogger.isAndroidLogAvailable()) {
            Object looperOrNull = getAndroidMainLooperOrNull();
            return looperOrNull == null ? null :
                    new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);
        } else {
            return null;
        }
    }

判断是否是null,刚来肯定是的;看一下else if

(Logger.AndroidLogger.isAndroidLogAvailable()

这是什么玩意儿?追进去看看

public interface Logger {

    ......

    public static class AndroidLogger implements Logger {
        static final boolean ANDROID_LOG_AVAILABLE;

        static {
            boolean android = false;
            try {
                android = Class.forName("android.util.Log") != null;
            } catch (ClassNotFoundException e) {
                // OK
            }
            ANDROID_LOG_AVAILABLE = android;
        }

        public static boolean isAndroidLogAvailable() {
            return ANDROID_LOG_AVAILABLE;
        }
        ......
    }
    ......
}

看方法名:isAndroidLogAvailable,Android的Log是否可用,判断条件就是看是否能找的到android系统的log类:

android = Class.forName("android.util.Log") != null;

找不到说明这事没得谈,你一个Android APP程序,你找不到android.util.Log,你还是在Android代码中?还谈什么主(UI)线程啊!(浅见啊,比较肤浅)

现在假设这事是定的,就直接走的else if代码;

Object looperOrNull = getAndroidMainLooperOrNull();
Object getAndroidMainLooperOrNull() {
        try {
            return Looper.getMainLooper();
        } catch (RuntimeException e) {
            // Not really a functional Android (e.g. "Stub!" maven dependencies)
            return null;
        }
    }

拿到主线程的Looper,如果拿不到返回null(注释:// Not really a functional Android (e.g. “Stub!” maven dependencies))

我们按照正常流程走,拿到主线程的Looper之后,

new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);

哎,牵扯的又有点远了…

/**
 * Interface to the "main" thread, which can be whatever you like. Typically on Android, Android's main thread is used.
 */
public interface MainThreadSupport {

    boolean isMainThread();

    Poster createPoster(EventBus eventBus);

    class AndroidHandlerMainThreadSupport implements MainThreadSupport {

        private final Looper looper;

        public AndroidHandlerMainThreadSupport(Looper looper) {
            this.looper = looper;
        }

        @Override
        public boolean isMainThread() {
            return looper == Looper.myLooper();
        }

        @Override
        public Poster createPoster(EventBus eventBus) {
            return new HandlerPoster(eventBus, looper, 10);
        }
    }

}

把主线程的Looper传进来,下次被调用isMainThread()时,直接拿当前线程的Looper和主线程对比判断;看这个接口名字起的,就是为主线程做支撑的;

现在回到正轨上;

判断当前线程是否是主线程;

然后判断当前发送事件是否取消了,取消就抛异常;没呢…

判断发送类型参数集合是否为空,凡事都要讲第一次,第一次肯定是不为空的

postSingleEvent(eventQueue.remove(0), postingState);

看方法名字:发送单个事件

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
        if (eventInheritance) {
            List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
            int countTypes = eventTypes.size();
            for (int h = 0; h < countTypes; h++) {
                Class<?> clazz = eventTypes.get(h);
                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));
            }
        }
    }

看传进来的参数,第一个:取出并移除参数队列中的第一个参数、第二个参数:线程发送状态对象;

获取传进来参数的class,(还记得之前的约定名词吗将订阅者和包装过的订阅方法SubscriberMethod组装的Subscription,我叫他订阅者方法),设置一个是否找到订阅者方法的标签subscriptionFound,默认false;

eventInheritance:神奇的东西,设置参数类型的继承性,假设参数类型A继承于B并实现了C接口,当设置为true的时候,发送A类型的事件时,A、B、C参数类型的方法都能接收得到;默认是true;如果想动手脚的话,也就是在EventBusBuilder中设置不具有继承性;

进入if中:

List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
 /** Looks up all Class objects including super classes and interfaces. Should also work for interfaces. */
    private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {
        synchronized (eventTypesCache) {
            List<Class<?>> eventTypes = eventTypesCache.get(eventClass);
            if (eventTypes == null) {
                eventTypes = new ArrayList<>();
                Class<?> clazz = eventClass;
                while (clazz != null) {
                    eventTypes.add(clazz);
                    addInterfaces(eventTypes, clazz.getInterfaces());
                    clazz = clazz.getSuperclass();
                }
                eventTypesCache.put(eventClass, eventTypes);
            }
            return eventTypes;
        }
    }
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();

又是一个Map,为什么要说又?

看一下代码可以知道:Key是传进来的参数类型的class,Value是eventTypes,eventTypes是一个List,里面装载的是参数类型;看到这里是不是有点蒙蔽,把自己做Key,又把自己塞到List中做Value,有病吧!但是别忘了,我们是从if进来的,if代表什么,参数类型有继承性,也就是具有"传染病仔细看,里面有个while方法

while (clazz != null) {
    eventTypes.add(clazz);
    addInterfaces(eventTypes, clazz.getInterfaces());
    clazz = clazz.getSuperclass();
}

这时干啥?这就是找到所有的"感染者";

先把自己塞到List中;

/** Recurses through super interfaces. */
    static void addInterfaces(List<Class<?>> eventTypes, Class<?>[] interfaces) {
        for (Class<?> interfaceClass : interfaces) {
            if (!eventTypes.contains(interfaceClass)) {
                eventTypes.add(interfaceClass);
                addInterfaces(eventTypes, interfaceClass.getInterfaces());
            }
        }
    }

把容器扔进去,把所有接口扔进去;只要有某个接口类型没有加到容器中就扔进去,然后是接口的接口,递归的把所有接口类型都扔进去,然后跳到父类中,把父类扔进去,接着找接口扔;

最终把所有的父类、接口类型都扔到集合里面,然后将该参数类型对应的这一List集合扔到Map中,并返回所有的事件类型;

拿到所有的事件类型后开始遍历;

postSingleEventForEventType(event, postingState, clazz);

传入的参数是post进来的事件类型对象,状态对象,遍历的事件类型

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> 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 {
                    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;
    }

有一个subscriptionsByEventType,妈的,Map;

用参数类型的class作为Key,所有的该参数类型的订阅者方法的List作为Value;

找到所有的订阅者方法;

只要注册过了就不会为null;还是第一次,不为空;

取得参数类型对象和订阅者方法,并设置一个aborted标签,它是用于判断post事件是否被取消;

private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch (subscription.subscriberMethod.threadMode) {
            ......
            case MAIN:
                if (isMainThread) {
                    invokeSubscriber(subscription, event);
                } else {
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            ......
        }
    }

这里只关注Main,

判断是否是主线程而执行不同的方法,我们是默认走的主线程;

void invokeSubscriber(Subscription subscription, Object event) {
        try {
            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
        } catch (InvocationTargetException e) {
            handleSubscriberException(subscription, event, e.getCause());
        } catch (IllegalAccessException e) {
            throw new IllegalStateException("Unexpected exception", e);
        }
    }

根据参数订阅者对象,订阅者参数值,直接反射调用订阅方法;

主线程的是走完了,那再来看看非主线程中执行的方法;

mainThreadPoster.enqueue(subscription, event);

传进来的参数是订阅者方法对象和参数对象;
mainThreadPoster这个是什么?还记得mainThreadSupport吧,默认使用mainThreadSupport的createPoster

@Override
public Poster createPoster(EventBus eventBus) {
    return new HandlerPoster(eventBus, looper, 10);
}

创建了一个HandlerPoster对象;

public class HandlerPoster extends Handler implements Poster {

    private final PendingPostQueue queue;
    private final int maxMillisInsideHandleMessage;
    private final EventBus eventBus;
    private boolean handlerActive;

    protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
        super(looper);
        this.eventBus = eventBus;
        this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!handlerActive) {
                handlerActive = true;
                if (!sendMessage(obtainMessage())) {
                    throw new EventBusException("Could not send handler message");
                }
            }
        }
    }

    @Override
    public void handleMessage(Message msg) {
        boolean rescheduled = false;
        try {
            long started = SystemClock.uptimeMillis();
            while (true) {
                PendingPost pendingPost = queue.poll();
                if (pendingPost == null) {
                    synchronized (this) {
                        // Check again, this time in synchronized
                        pendingPost = queue.poll();
                        if (pendingPost == null) {
                            handlerActive = false;
                            return;
                        }
                    }
                }
                eventBus.invokeSubscriber(pendingPost);
                long timeInMethod = SystemClock.uptimeMillis() - started;
                if (timeInMethod >= maxMillisInsideHandleMessage) {
                    if (!sendMessage(obtainMessage())) {
                        throw new EventBusException("Could not send handler message");
                    }
                    rescheduled = true;
                    return;
                }
            }
        } finally {
            handlerActive = rescheduled;
        }
    }
}

继承于Handler,所以他也是一个handler;

执行了enqueue方法;

又牵扯出一个PendingPost,

final class PendingPost {
    private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();

    Object event;
    Subscription subscription;
    PendingPost next;

    private PendingPost(Object event, Subscription subscription) {
        this.event = event;
        this.subscription = subscription;
    }

    static PendingPost obtainPendingPost(Subscription subscription, Object event) {
        synchronized (pendingPostPool) {
            int size = pendingPostPool.size();
            if (size > 0) {
                PendingPost pendingPost = pendingPostPool.remove(size - 1);
                pendingPost.event = event;
                pendingPost.subscription = subscription;
                pendingPost.next = null;
                return pendingPost;
            }
        }
        return new PendingPost(event, subscription);
    }

    static void releasePendingPost(PendingPost pendingPost) {
        pendingPost.event = null;
        pendingPost.subscription = null;
        pendingPost.next = null;
        synchronized (pendingPostPool) {
            // Don't let the pool grow indefinitely
            if (pendingPostPool.size() < 10000) {
                pendingPostPool.add(pendingPost);
            }
        }
    }

}

看名字:PendingPost,等待发送;

内部维持了一个池子,大小小于10000,用完之后把对象值清空扔进池子,用的时候从池子尾部取出并移除一个空值对象,然后赋值,并将该对象返回;如果池子是空的,则新建一个等待post对象并赋值返回;

回到HandlerPoster中,获取到一个等待post对象后;

final class PendingPostQueue {
    private PendingPost head;
    private PendingPost tail;

    synchronized void enqueue(PendingPost pendingPost) {
        if (pendingPost == null) {
            throw new NullPointerException("null cannot be enqueued");
        }
        if (tail != null) {
            tail.next = pendingPost;
            tail = pendingPost;
        } else if (head == null) {
            head = tail = pendingPost;
        } else {
            throw new IllegalStateException("Head present, but no tail");
        }
        notifyAll();
    }

    synchronized PendingPost poll() {
        PendingPost pendingPost = head;
        if (head != null) {
            head = head.next;
            if (head == null) {
                tail = null;
            }
        }
        return pendingPost;
    }

    synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {
        if (head == null) {
            wait(maxMillisToWait);
        }
        return poll();
    }

}

看代码就是一个链表的节点类;执行enqueue方法,如果是第一个则将头尾指针指向该等待post对象,否则就是往尾上加,最后唤醒该线程,抢夺时间片执行;

设置一个handlerActive标签,是否正在处理中,在里面发送事件,同时handleMessage相应执行;

还记得HandlerPoster是在哪创建的吧,没错,是在主线程中创建的,所以handleMessage是在主线程中执行的,不要切换线程了(假设更新UI的话);

记录开始的时间,然后死循环进去如果链表空了,那就中断了,否则就执行

eventBus.invokeSubscriber(pendingPost);

先不管,往下看,最后handlerActive标签改变,退出死循环,方法结束;

取得当前时间与开始时间的时间差,只要大于10毫秒(为什么是10毫秒,传进来的就是10毫秒),就重发消息,这是为了避免队列过长是,while循环阻塞主线程造成卡顿。

再回过头来看看eventBus.invokeSubscriber(pendingPost);

void invokeSubscriber(PendingPost pendingPost) {
        Object event = pendingPost.event;
        Subscription subscription = pendingPost.subscription;
        PendingPost.releasePendingPost(pendingPost);
        if (subscription.active) {
            invokeSubscriber(subscription, event);
        }
    }

拿到参数对象,拿到订阅者方法,释放等待post占用的资源内存;

只要没有解注册,就调用invokeSubscriber(subscription, event);看来殊途同归啊,也是反射调用订阅方法;

这里就结束了,post事件就发送出去了;

接着往回填坑;

不管主线程还是非主线程方法执行完之后,也就是postToSubscription方法结束了;
最终发送状态postingState释放资源内存;且返回true;没有没有找到订阅者方法,就返回false;

只要找到了subscriptionFound标签就会为true;

如果没有参数类型的继承性,就只会执行当前参数的

subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);

效果和之前一样;

同样如果没有找到订阅者方法,sendNoSubscriberEvent默认是true;直接发送一个NoSubscriberEvent类型的事件通知;到了post方法中,NoSubscriberEvent对象被添加到了eventQueue中,但是此时isPosting还是true,被拦截了进不去if,postSingleEvent事件结束,但是由于eventQueue中添加了NoSubscriberEvent事件,所以while并没有结束,再次调用postSingleEvent,这时的参数是NoSubscriberEvent对象,这次是肯定找不到NoSubscriberEvent类型的订阅者方法的,所以subscriptionFound=false,又进入了if判断中,但是这次

eventClass != NoSubscriberEvent.class

该条件不成立,所以该方法结束,然后post中的while因为没数据了也结束了循环,postingState释放剩下的占用资源内存;

到这里彻底结束了普通事件的post。

参考:

Java并发编程:深入剖析ThreadLocal


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值