EventBus

以前试着看过Android其他源码, 后来感觉是一脸懵逼, 并且经常是只顾着把代码意思搞懂就以为完事, 然后没过多久就忘了, 这次看源码看了些资料, 发现如果能试着去理解作者的套路, 效果或许会好一些, 并且可能会学到点儿技巧.
EventBus源码其实挺简单, 类的数量也不多.

1.从一个小demo开始:

其实平时工作中用到最多的也就是这几个方法;

这里写图片描述

2.试着分析源码:
EventBut.getDefault().register(this);

这里写图片描述

作者使用的是volatile关键字创建的单例模式, 我可以把volatile提出来, 不是说我想说单例模式的正确写法, 而是顺便给自己提个醒, 现在volatile我也看的是一知半解, 等我把深入理解Java虚拟机看完, 我就开始看Java并发编程, 绝世好书啊, 这是我查资料看到volatile博客的感想, 这里不对volatile做总结, 总结不出来, 只贴一个链接:
http://www.cnblogs.com/dolphin0520/p/3920373.html
然后开始register(Object subscriber):

这里写图片描述
这里写图片描述

看源码时有一个小套路, 不一定从头到尾看, 有返回值时先从return下手, 返回值是subScriberMethods

List<SubScriberMethod> subScriberMethods = METHOD_CACHE.get(subScriberClass);

接下来从ignoreGeneratedIndex开始, 定位该变量发现, 他的默认值为false, 去官方文档查了一下, EventBus3.0之前使用的是findUserReflection();3.0之后使用的是findUsingInfo(); 至于为何, 后面把两个方法分析完再做总结.

接下来看findUsingReflection();

这里写图片描述

还是先从getMethodsAndRelease(findState)入手

这里写图片描述

这里其实也值得我们借鉴, 注意getMethodsAndRelease()与prepareFindState()这两个方法里面的FIND_STATE_POOL这个数组, 我看到有些地方说是为了防止并发, 但是貌似并发跟这个复用池的思想用时取出, 用完放回并没有什么关系, 他用的是synchronized保证的线程同步, ListArray的底层也是数组, 他直接操作数组, 先让数组每一为置为null, 然后不断的替换对应位置的null, 然后不断取出放回, 这些操作的时间复杂度都是O[1], 这样做的目的应该是这里, 降低时间复杂度.

然后切到initForSubscriber方法:

这里写图片描述

该方法仅仅是进行了赋值操作.

然后切入到findUsingReflectionInSingleClass()方法:

这里写图片描述

里面有几个地方需要关注一哈
1. getDeclaredMethods()getMethods();

getDeclaredMethods()返回自身的方法, getMethods()返回包括父类中的public方法(不包括native方法)

2. 一系列方法说明EventBus的规定:

1、if(modifiers & Modifier.PUBLIC)!=0… ->对订阅方法格式做了要求, 只能是public

2、parameterTypes.length == 1 -> 方法的形参个数只能为1

我们之前返回的值为findState.subscriberMethods

final List<SubscriberMethod> subscriberMethods = new ArrayList<>();

集合一定要重点关注get和add方法, add出现在

if (findState.checkAdd(method, eventType)) {
    SubscriberMethod subscriber; 
    subscriber = new SubscriberMethod(method, 
                                      eventType, 
                                      threadMode,
                                      subscribeAnnotation.priority(), 
                                      subscribeAnnotation.sticky()));
    findState.subscriberMethods.add(subscriber);
}

如果要保证程序正常执行, 就一定要保证checkAdd的返回值为true;
切入到checkAdd():

这里写图片描述

1、如果是第一次进入, 返回true
2、如果第二次进入, 切入到checkAddWithMethodSignature()方法:

这里写图片描述

a.isAssiginableFrom(b)//a与b相同或者是b的父类或者父接口,则返回true

暂时只发现该方法一定返回true, 不知道else{…}何时才会执行
然后我们回到findUsingReflectionInSingleClass方法

这里写图片描述

在平时使用过程中, 我们一般都是这样操作的

@Subscribe
public void onMessage(Object obj){...}

切入到Subscribe

这里写图片描述

1、threadMode默认为PISTING
2、ThreadMode类型:POSTING、MAIN、BACKGROUND、ASYNC

EventBus3.0之前的方法分析完了

接下来看看EventBus3.0之后的方法:

findUsingInfo():

这里写图片描述

然后在执行到getSubscriberInfo(findState)以后发现findState.subscribeInfo == null, 最终还是执行到else中, 查看文档才知道需要我们自己去配置,然后才会执行3.0以后这个新加的逻辑.

至此EventBus.getDefault().register(this)分析完了.
然后我们来分析EventBus.getDefault().post()方法:

这里写图片描述
这里写图片描述

采用ThreadLocal模式, 一个线程对应一个PostingThreadState; 他这种写法如果以后在工作中遇到, 我们就可以这样模仿一哈.

1、将event添加到消息队列中;
2、isPosting默认为false;
3、判断当前线程是否是主线程;
4、切入到postSingleEvent();

这里写图片描述

该方法中重点关注两个方法:

1、lookupAllEventTypes(eventClass);

2、subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);

切入到 lookupAllEventTypes(eventClass);

这里写图片描述

方法如其名, 采用递归的方式将Event对象及其父类, 父接口添加到eventClass中;暂时可能会有疑惑, 不知道为何要讲父类父接口全部添加到eventClass中, 我们继续向后看, 没准就会有所收获.

这里写图片描述

1、最终利用反射调用目标方法;
2、如果定义ThreadModel.threadModel = MAIN, 但是我们在子线程直接调用post方法会发生什么现象呢?

threadModel = ThreadMode.POSTING:
这里写图片描述

threadModel = ThreadMode.MAIN:

这里写图片描述

这个源码当我们使用MAIN模式时, 在子线程进行post时, EventBus内部使用Handler模式帮我们把消息切换到主线程了.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值