简读Eventbus3.0

简单了解一下eventbus的工作情况,学学大神的思想,那么在此篇文章之前呢,建议大家先要了解清楚何为注解和反射,如果没了解,可以先看看前一篇文章,有具体的介绍  Android 注解 (Annotation)

使用过eventbus的都知道,eventbus是一个Android事件发布/订阅轻量级框架, 它可以完美的在任何地方完成通信任务,那么不废话啦,按照 咱们在Android中的使用过程为思路展开一个了解吧

一、我们是在需要接受事件的地方(例如activity、fragment) 注册 eventbus事件

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(...);
        //注册eventbus事件
        EventBus.getDefault().register(this);
     
    }

好啦,如上代码,我们在activity的oncreate生命周期方法中注册了eventbus事件,那么来看一下 getDefault()、register()方法到底干了点什么

//第一部分,获取单例(懒汉式,"懒得创建自己")
public static EventBus getDefault() {
        if (defaultInstance == null) {
            synchronized (EventBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    }


//第二部分,注册给定的订阅服务器以接收事件。订阅者必须调用{unregister(Object)取消注册(对象)}
public void register(Object subscriber) {
        //1.首先通过反射获取到当前类
        Class<?> subscriberClass = subscriber.getClass();
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);//2
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);//3
            }
        }
    }

      第一部分 EventBus.getDefault() 是一个懒汉式单例。                                                                              

      第二部分是注册,1.首先通过当前object.getclass()反射方法获取到当前 class对象;    2.然后通过 findSubscriberMethods 方法获取到一个当前class对象的所有方法,并放在一个list集合中,List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass); 该行代码中就是就是维护了 一个 ConcurrentHashMap 对象 ; 3.接下来就是一个 synchronized 同步块,把该类和该类的多个方法进行配对订阅

 

二、发送提交和订阅消费

提交事件到总线:  EventBus.getDefault().post(object);

//将给定事件提交到事件总线
public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get(); //1
        List<Object> eventQueue = postingState.eventQueue;
        eventQueue.add(event);

        if (!postingState.isPosting) {//2
            postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
            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);//3
                }
            } finally { //最终把状态都还原了
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }

//-------------------current Posting Thread State --------------------------

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



//------------------Posting Thread State------------------------

/** For ThreadLocal, much faster to set (and get multiple values). */
final static class PostingThreadState {
        final List<Object> eventQueue = new ArrayList<Object>(); //消息集合
        boolean isPosting; //是否有发送
        boolean isMainThread; //是否是主线程
        Subscription subscription; //订阅关系
        Object event; //具体发送的事件体
        boolean canceled; //是否取消了
    }

 1. PostingThreadState postingState = currentPostingThreadState.get() 该方法其实就是ThreadLocal对象(线程副本,为线程本身存储变量等信息),而PostingThreadState就是线程副本内所存储JavaBean对象 (在此可以看出,该bean对象并没有get set封装),从bean对象中获取到消息集合,并把当前post所要提交的消息保存在该集合中;

 2. 使用 isposting 来判断是否发送过信息,然后进入下一步判断当前发送post方法执行的线程是否是主线程,设置发送状态,判断消息是否有效,while遍历

3. while在集合非空状态下,会不断遍历 postSingleEvent 方法,不断从集合中获取消息体和副本中数据进行处理,那么在往下查看有  postToSubscription(subscription, event, postingState.isMainThread) 这样的方法,它主要就是获取咱们标签中的value,根据不同的value 在不同的线程做不同的操作

//常用的四个标签
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch (subscription.subscriberMethod.threadMode) {
            case POSTING://当前线程执行
                invokeSubscriber(subscription, event);
                break;
            case MAIN: //事件的消费会在UI线程。因此,不宜进行耗时操作,以免引起ANR
                if (isMainThread) {
                    invokeSubscriber(subscription, event);
                } else {
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            case BACKGROUND://背景线程,如果事件在UI线程产生,那么事件的消费会在单独的子线程中进行。否则,在同一个线程中消费。
                if (isMainThread) {
                    backgroundPoster.enqueue(subscription, event);
                } else {
                    invokeSubscriber(subscription, event);
                }
                break;
            case ASYNC://异步执行,不管是否在UI线程产生事件,都会在单独的子线程中消费事件
                asyncPoster.enqueue(subscription, event);
                break;
            default:
                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
        }
    }


//---------------------反射中的 方法执行---------------------------

void invokeSubscriber(Subscription subscription, Object event) {
        try {
            //通过反射获取到要执行的方法 subscription.subscriber,该方法的参数就是 通过 post要提交的消息
            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
        } catch (InvocationTargetException e) {
            handleSubscriberException(subscription, event, e.getCause());
        } catch (IllegalAccessException e) {
            throw new IllegalStateException("Unexpected exception", e);
        }
    }

三、注销

EventBus.getDefault().unregister(this);

//每个待消费事件的class都会对应一个list集合
private final Map<Object, List<Class<?>>> typesBySubscriber;
//取消注册
public synchronized void unregister(Object subscriber) {
        //获取该activity或fragment对应的注解类
        List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            // 遍历所有的订阅方法 ,并取消
            for (Class<?> eventType : subscribedTypes) {
                unsubscribeByEventType(subscriber, eventType);
            }
            typesBySubscriber.remove(subscriber);
        } else {
            Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }
在使用的时候只是简单导入eventbus jar,我们调用的时候只要简单的注册和配置注解标签即可,极大提供了开发效率,这就是提供框架的好处;另外重要的一点,就是学习文中的“注册”与“注销”的精神,程序做到了有始有终,在开辟了内存,在内存中完成业务,然后在view组件结束生命周期的时候把所占的内存、操作都结束了       ;初次解读,有问题的地方要指出,互相提高吧

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章