美文网首页
EventBus源码分析及仿EventBus实现

EventBus源码分析及仿EventBus实现

作者: MEzzsy | 来源:发表于2019-01-21 18:48 被阅读0次

    EventBus源码分析

    我分析源码一般是从整体来进行分析,对于一些细节的东西,我没有时间也没有能力去分析。

    简单使用

    导入依赖

    implementation'org.greenrobot:eventbus:3.1.1'
    

    定义观察者

    public class MyObserver1 {
        public MyObserver1() {
            EventBus.getDefault().register(this);
        }
    
        @Subscribe
        public void myEvent(MyEvent event){
            System.out.println("我是观察者1,我观察到了");
        }
    }
    
    public class MyObserver2 {
        public MyObserver2() {
            EventBus.getDefault().register(this);
        }
    
        @Subscribe
        public void myEvent(MyEvent event) {
            System.out.println("我是观察者2,我观察到了");
        }
    }
    

    定义被观察者和测试

    public class MyObserved {
        public MyObserver1 observer1;
        public MyObserver2 observer2;
    
        public MyObserved() {
            observer1 = new MyObserver1();
            observer2 = new MyObserver2();
        }
    
        public static void main(String[] args) {
            MyObserved observed = new MyObserved();
            Scanner in = new Scanner(System.in);
            while (true) {
                int code = in.nextInt();
                if (code == 1) {
                    observed.sendEvent();
                } else {
                    EventBus.getDefault().unregister(observed.observer1);
                    EventBus.getDefault().unregister(observed.observer2);
                    break;
                }
            }
        }
    
        public void sendEvent() {
            MyEvent event = new MyEvent();
            EventBus.getDefault().post(event);
        }
    }
    

    输出

    1
    我是观察者1,我观察到了
    我是观察者2,我观察到了
    1
    我是观察者1,我观察到了
    我是观察者2,我观察到了
    2
    

    具体分析

    这里就从上面使用到的方法来进行分析。

    入口方法

    getDefault()

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

    这里就是采用双重校验并加锁(DCL)的单例模式生成EventBus实例。

    注册

    register()

    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(Class<?> subscriberClass)

    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);//获取缓存
        if (subscriberMethods != null) {
            return subscriberMethods;
        }
    
        if (ignoreGeneratedIndex) {
            subscriberMethods = findUsingReflection(subscriberClass);
        } else {
            subscriberMethods = findUsingInfo(subscriberClass);
        }
        //。。。省略
    }
    

    findUsingReflection(Class<?> subscriberClass)

    private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
        //...
            findUsingReflectionInSingleClass(findState);
        //...
    }
    

    findUsingReflectionInSingleClass(FindState findState)

    private void findUsingReflectionInSingleClass(FindState findState) {
        Method[] methods;
        try {
            methods = findState.clazz.getDeclaredMethods();
        } catch (Throwable th) {
            methods = findState.clazz.getMethods();
            findState.skipSuperClasses = true;
        }
        for (Method method : methods) {
            Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
            if (subscribeAnnotation != null) {
                Class<?> eventType = parameterTypes[0];
                if (findState.checkAdd(method, eventType)) {
                    ThreadMode threadMode = subscribeAnnotation.threadMode();
                    findState.subscriberMethods.add(new SubscriberMethod(method, eventType,threadMode,subscribeAnnotation.priority(),subscribeAnnotation.sticky()));
                }
            }
        } 
        //...
    }
    

    以上几个方法的大致逻辑就是先看有没有SubscriberMethod的缓存,有的话直接用,没有的话就找出添加了@Subscribe注解的方法。在findUsingReflectionInSingleClass方法里也可以看到很明显的以反射机制处理注解的逻辑。

    SubscriberMethod类

    public class SubscriberMethod {
        final Method method;
        final ThreadMode threadMode;
        final Class<?> eventType;
        final int priority;
        final boolean sticky;
        /** Used for efficient comparison */
        String methodString;
    
        //...
    }
    

    从成员变量可以看出这个SubscriberMethod是用来封装观察者的添加了Subscribe注解的方法,观察者有一个观察方法就有一个SubscriberMethod。

    最终封装

    上面的register方法只看了一部分,还有下面一部分。

    public void register(Object subscriber) {
        //...
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }
    

    这里将观察者的每个观察方法进行最终封装。

    subscribe(Object subscriber, SubscriberMethod subscriberMethod)

    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class<?> eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        CopyOnWriteArrayList<Subscription> 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);
            }
        }
        //。。。
    }
    

    上面的逻辑就是为了避免二次注册,而我省略的部分可以总结为将Subscription添加进容器里。

    Subscription类

    final class Subscription {
        final Object subscriber;
        final SubscriberMethod subscriberMethod;
        //...
    }
    

    主要封装了观察者对象和其方法

    EventBus有个关键的成员变量:

    private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
    

    这个Map以事件类型为键,对应的观察方法的容器为值。

    而Subscription封装好了之后就是放入这个Map里的。

    发送

    post()

    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;
            }
        }
    }
    

    post主要逻辑就是根据传入的事件,根据其事件类型(Class<?>)从subscriptionsByEventType取出对应事件类型的Subscription,然后利用反射机制,调用方法。

    仿EventBus实现

    这里就根据上面的分析来实现一个简单的EventBus。

    构造单例对象

    private HashMap<Class<?>, ArrayList<Observation>> mObserverArrayListHashMap;
    
    private MyEventBus() {
        mObserverArrayListHashMap = new HashMap<>();
    }
    
    public static MyEventBus getDefault() {
        return SingletonHolder.SINGLETON;
    }
    
    private static class SingletonHolder {
            private static final MyEventBus SINGLETON = new MyEventBus();
        }
    

    这里我采用静态内部类的方式实现单例模式

    注册

    public void register(Object observer) {
        Class<?> observerClass = observer.getClass();
        List<ObserverMethod> observerMethods = findObserverMethods(observerClass);
        for (ObserverMethod observerMethod : observerMethods) {
            observe(observer, observerMethod);
        }
    }
    
    private List<ObserverMethod> findObserverMethods(Class<?> observerClass) {
            List<ObserverMethod> observerMethods = new ArrayList<>();
            for (Method method : observerClass.getDeclaredMethods()) {
                Observe observe = method.getAnnotation(Observe.class);
                if (observe != null) {
                    Class<?> eventType = method.getParameterTypes()[0];
                    ObserverMethod observerMethod = new ObserverMethod(method, eventType);
                    observerMethods.add(observerMethod);
                }
            }
            return observerMethods;
        }
        
    private void observe(Object observer, ObserverMethod observerMethod) {
            Class<?> eventType = observerMethod.getEventType();
            Observation observation = new Observation(observer, observerMethod);
            ArrayList<Observation> observations = mObserverArrayListHashMap.get(eventType);
            if (observations == null) {
                observations = new ArrayList<>();
                mObserverArrayListHashMap.put(eventType, observations);
            } else {
                if (observations.contains(observation)) {
                    return;
                }
            }
            observations.add(observation);
        }
    

    两个封装类

    class ObserverMethod {
        private Method mMethod;
        private Class<?> mEventType;
    
        public ObserverMethod(Method method, Class<?> eventType) {
            mMethod = method;
            this.mEventType = eventType;
        }
    
        public Method getMethod() {
            return mMethod;
        }
    
        public Class<?> getEventType() {
            return mEventType;
        }
    }
    
    class Observation {
        private Object observer;
        private ObserverMethod observerMethod;
    
        public Observation(Object observer, ObserverMethod observerMethod) {
            this.observer = observer;
            this.observerMethod = observerMethod;
        }
    
        public Object getObserver() {
            return observer;
        }
    
        public ObserverMethod getObserverMethod() {
            return observerMethod;
        }
    }
    

    发送

    public void post(Object event) {
        Class<?> eventType = event.getClass();
        ArrayList<Observation> observations = mObserverArrayListHashMap.get(eventType);
        if (observations == null) {
            return;
        }
        for (Observation observation : observations) {
            Object observer = observation.getObserver();
            Method method = observation.getObserverMethod().getMethod();
            try {
                method.invoke(observer, event);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
    

    测试

    观察者

    public class MyObserver1 {
        public MyObserver1() {
            MyEventBus.getDefault().register(this);
        }
    
        @Observe
        public void myEvent(MyEvent event){
            System.out.println("我是观察者1,我观察到了");
        }
    }
    
    public class MyObserver2 {
        public MyObserver2() {
            MyEventBus.getDefault().register(this);
        }
    
        @Observe
        public void myEvent(MyEvent event){
            System.out.println("我是观察者2,我观察到了");
        }
    }
    

    事件

    public class MyEvent {
    }
    

    被观察者及测试

    public class MyObserved {
        public MyObserved() {
            MyObserver1 observer1 = new MyObserver1();
            MyObserver2 observer2 = new MyObserver2();
        }
    
        public static void main(String[] args) {
            MyObserved observed = new MyObserved();
            Scanner in = new Scanner(System.in);
            while (true) {
                int code = in.nextInt();
                if (code == 1) {
                    observed.sendEvent();
                } else {
                    break;
                }
            }
        }
    
        public void sendEvent() {
            MyEvent event = new MyEvent();
            MyEventBus.getDefault().post(event);
        }
    }
    
    output:
    1
    我是观察者1,我观察到了
    我是观察者2,我观察到了
    1
    我是观察者1,我观察到了
    我是观察者2,我观察到了
    2
    
    Process finished with exit code 0
    

    相关文章

      网友评论

          本文标题:EventBus源码分析及仿EventBus实现

          本文链接:https://www.haomeiwen.com/subject/qdocjqtx.html