android EventBus源码原理分析

本文的源码使用到EventBus3.2.0版本
本文所示的源码将会忽略与核心逻辑无关的代码,被忽略的代码将使用省略号表示

以下为eventBus最简单的使用代码:

public class TestActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    	//	注册eventbus
        EventBus.getDefault().register(this);.
        //	发送消息
        EventBus.getDefault().post(new Object());
	}
	
	//	添加消息监听注解
	@Subscribe()
    public void onEvent(Event event){
        Log.d("test","接收到消息");
    }
}

该代码运行后将会打印,“接收到消息”;

EventBus注册原理

那么接下来分析代码“EventBus.getDefault().register(this)”,干了什么

    public void register(Object subscriber) {
    	//	获取订阅者的class对像
        Class<?> subscriberClass = subscriber.getClass();
        // 获取所有带有注解“@Subscribe”的方法
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        ...
    }

我们继续进入“subscriberMethodFinder.findSubscriberMethods(subscriberClass)”方法中:

 List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
		...
        if (ignoreGeneratedIndex) {
        	//默认走这里
            subscriberMethods = findUsingReflection(subscriberClass);
        } else {
            subscriberMethods = findUsingInfo(subscriberClass);
        }
        ....
    }
    
    // 命名知意,使用反射方式查找
    private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
        FindState findState = prepareFindState();
       ...
            findUsingReflectionInSingleClass(findState);
        ...
        return getMethodsAndRelease(findState);
    }
    
    private void findUsingReflectionInSingleClass(FindState findState) {
        Method[] methods;
        ...
        // 获取订阅者对象的所有方法
        methods = findState.clazz.getDeclaredMethods();
        ...
         //遍历所有方法
        for (Method method : methods) {
           ...
             	// 核心!核心!核心!
                Class<?>[] parameterTypes = method.getParameterTypes();
                // 过滤只有一个参数的方法
                if (parameterTypes.length == 1) {
                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                   // 找出带有“Subscribe”注解的方法
                    if (subscribeAnnotation != null) {
                        Class<?> eventType = parameterTypes[0];
                        if (findState.checkAdd(method, eventType)) {
                            ThreadMode threadMode = subscribeAnnotation.threadMode();
                            // 新建一个订阅者方法对象,并缓存到subscriberMethods队列中
                            findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                    subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                        }
                    }
                } 
		...
        }
    }

好了,简单来说,EventBus注册其实就是找出被注册对象中所有带有@Subscribe注解的方法,并缓存起来!

EventBus发送消息原理

我们一起来看看 "EventBus.getDefault().post(new Object())"干了什么

	public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> eventQueue = postingState.eventQueue;
        // 将消息加入到队列中
        eventQueue.add(event);
        ...
          while (!eventQueue.isEmpty()) {
          		// 遍历队列,并执行postSingleEvent
                postSingleEvent(eventQueue.remove(0), postingState);
            }
		...
        }
    }

	private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
		// 获取event的class对象,本事例是Object,实际使用将会是自定义的一个实体类
        Class<?> eventClass = event.getClass();
        ... //剔除了所有非核心代码
        // lookupAllEventTypes方法实际是找出event对象的所有基类,这里不多介绍,有兴趣的自己跟源码
         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);
         }
         ...
    }	
	// 核心!核心!核心
   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) {
				...
                    postToSubscription(subscription, event, postingState.isMainThread);
                ...
            }
            return true;
        }
        return false;
    }
    
	private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
		// 忽略各种线程调度代码
		   ...
	            invokeSubscriber(subscription, event);
	       ...
	    }
    
	//最终到这里
    void invokeSubscriber(Subscription subscription, Object event) {
       	...
       		// 反射执行订阅者的方法,并传递event对象
            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
		...
    }

所以,简单来说,EventBus消息发送就是通过event对象找出在注册时所缓存的订阅者方法,然后执行!

原理总结

一句话,注册就是以反射方式缓存订阅者方法,发送消息就是以反射方式执行已缓存的订阅者方法。
核心实现原理仅用到Java反射机制!

OK,就这么多!用帮助的话,点个赞!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大炮走火

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值