android源码--androidEventBus分析

知识点:
1.CopyOnWriteArrayList
什么是CopyOnWrite容器
  CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。

2.CopyOnWrite的缺点
  CopyOnWrite容器有很多优点,但是同时也存在两个问题,即内存占用问题和数据一致性问题。所以在开发的时候需要注意一下。
内存占用问题。因为CopyOnWrite的写时复制机制,所以在进行写操作的时候,内存里会同时驻扎两个对象的内存,旧的对象和新写入的对象(注意:在复制的时候只是复制容器里的引用,只是在写的时候会创建新对象添加到新容器里,而旧容器的对象还在使用,所以有两份对象内存)。如果这些对象占用的内存比较大,比如说200M左右,那么再写入100M数据进去,内存就会占用300M,那么这个时候很有可能造成频繁的Yong GC和Full GC。

针对内存占用问题,可以通过压缩容器中的元素的方法来减少大对象的内存消耗,比如,如果元素全是10进制的数字,可以考虑把它压缩成36进制或64进制。或者不使用CopyOnWrite容器,而使用其他的并发容器,如ConcurrentHashMap。

数据一致性问题。CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器。

3.ConcurrentHashMap 和 HashMap 思路是差不多的,支持并发操作

4.ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获取到存储的数据,对于其它线程来说无法获取到数据。

androidEventBus使用的观察者模式:
观察者:
1.首先是订阅者进行订阅
android源码--androidEventBus分析
在activity中使用注解来确定订阅的方法,tag相当于广播的action,在方法中只能填一个参数。参数类型不限制。
android源码--androidEventBus分析
2.在EventBus类中进行注册,使用mMethodHunter类,主要是负责维护事件和订阅者之间的map关系
android源码--androidEventBus分析
3.在SubscribeMethodHunter类中,将通过订阅的类获取里面加入注解的方法,因为支持一个参数,因此进行过滤
android源码--androidEventBus分析
这个方法就是将通过类型和订阅者存在map中
android源码--androidEventBus分析
而这个map定义的就是类型如下,主要是tag—subscriber之间的映射
android源码--androidEventBus分析
4.对于里面的各个数据类型
EventType类型,主要是当做map的key
android源码--androidEventBus分析
Subscription类型,主要为map的value
android源码--androidEventBus分析
被观察者:
1.调用
android源码--androidEventBus分析
2.发布方法
android源码--androidEventBus分析
android源码--androidEventBus分析
//用ThreadLocal的目的就是能存储各个线程的数据
android源码--androidEventBus分析
//这里是重点:这里通过getMatchedEventTypes()方法返回一系列的EventType对象,这些对象严格意义上是在注册时候的存储在map中的对象不同,所以正常情况下是不同通过通过这里eventType和mSubscriberMap进行匹配成功的,这里重写了这个类的equals()方法和hashCode()方法,导致如果有相同的参数,那么就判断为同一个对象。
android源码--androidEventBus分析
//有可能在父类中的某个方法也添加了相应的注解,这样就能让父类也能收到数据
android源码--androidEventBus分析
//获取所有的类型,这么做的目的应该是为了提高兼容性。
android源码--androidEventBus分析
android源码--androidEventBus分析
//使用handler能够解决跨线程的问题
android源码--androidEventBus分析
//最终是通过反射调用添加注解的方法,最终是调用相应对象的方法
android源码--androidEventBus分析

补充:重写EventType对象的hashcode()和equals()方法,只要参数相同,就判断为同一个对象。
android源码--androidEventBus分析

具体的demo地址:https://github.com/yunzheyue/AndroidEventBusTest