zoukankan      html  css  js  c++  java
  • Android组件通信:Eventbus原理解析

    概述

    EventBus基于安卓优化的发布-订阅事件总线,本质上还是Java的观察者模式。消息接收者注册到Bus总线,消息发送后根据相应的消息类型分发消息。

    总的注册和消息发送流程如下

    源码解读

     观察者注册

    使用单例模式新建唯一EventBus实例

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

    注册观察者

    public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();//获取观察者的类
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);//使用反射拿到观察者类所有的监听对象
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);//订阅该对象和它的所有方法
            }
        }
    }

    订阅的时候按监听方法参数分类缓存到Bus总线

    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        ...
        Class<?> eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        ...
    }

    消息发送

    消息发送者通过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;
            }
        }
    }

     拿到消息发送者发送消息的类型

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

    使用反射方法的invoke方法唤起观察者的监听方法

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

    反注册

    根据观察者的类型移除事件总线中相应的观察者对象

    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 {
            logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }

    总结

    1. 由于使用注解,在实际业务开发中可能定位Bug有困难
    2. 使用方便,比Handler和广播方便
    3. 关键代码使用反射,性能可能有所下降
  • 相关阅读:
    我的死党前同事 料
    相信缘份吗?我所见所闻的测试工程师
    多线程基础【面试题形式】
    kafka学习(五)Spring Boot 整合 Kafka
    kafka学习(四)kafka安装与命令行调用
    J2EE的13个规范总结
    Spring Boot学习(四)常用注解
    kafka学习(三)kafka生产者,消费者详解
    dubbo学习(十一)dubbo知识点总结
    MyBatis学习(三)日志输出环境配置
  • 原文地址:https://www.cnblogs.com/billshen/p/13324624.html
Copyright © 2011-2022 走看看