EventBus源码分析

95 篇文章 0 订阅

在安卓开发中经常需要实现进程通信,和组件之间通信,代码实现比较繁琐,不够优雅。eventBus就能很好解决这个问题。

先简单介绍基本使用

在build.gradle配置

implementation 'org.greenrobot:eventbus:3.1.1'

 

//注册
EventBus.getDefault().register(this);

//注销
EventBus.getDefault().unregister(this);

//订阅消息
@Subscribe(threadMode = ThreadMode.POSTING)
public void getMessage(Bean bean) {
Log.e("main","------"+Thread.currentThread().getName());
}

//发送消息
EventBus.getDefault().post(new Bean("zhangsan",18));

 

使用很简单 在需要接受消息的类注册和注销eventbus,并且定义个方法使用subscriber注解 方法参数为发送的类型就Ok了。而且接受的对象不需要实现序列化,代码很简洁。那么eventbus是如何实现的呢,我们可以通过他的这四个方法解析他的基本原理

(备注我使用的是EventBus: 3.1.1)

先我们看看getDefault这个方法是个单利,使用了同步锁。

1注册:register(this)方法 先会调用SubscriberMethodFinder类的findSubscriberMethods(注册对象)方法,这个方法会 通过注册对象作为map的键,看获取的值是否为空,不为空就直接返回这个值;为空就通过注册类 反射获取注册类里面所有使用subscriber注解的方法信息 ,每个方法信息保存到SubscriberMethod类里面,再把所有SubscriberMethod类保存到一个list集合里面即subscriberMethods对象里面,再以注册类为键,subscriberMethods为值保存到map里面(METHOD_CACHE)。最后把subscriberMethods集合返回出去。

 

//获取 注册类里面使用subscriber注解方法集合后(subscriberMethods);遍历集合方法里面会调用subscribe()方法;

这个方法里面又调用subscriptionsByEventType.put(eventType, subscriptions)方法,subscriptionsByEventType就是一个map集合,作用就是以注册类的注解方法参数类型为键,以Subscription类的集合为值。(点击Subscription类进去看构造方法,参数就是注册类和SubscriberMethod类

//同时还会通过注册类为键 获取typesBySubscriber里面的值(也是个map); 如果返回的集合为空就,就通过注册类获取 注解方法参数类型保存到集合subscribedEvents,再以注册类为键 ,subscribedEvents集合(集合的保存类是订阅方法参数类)为值保存到typesBySubscriber这个map里面。

//至此注册工作就做完了,(其实注册工作就是以注册类为键从三个map获取值 ,看值是否为空,为空就保存信息,不为空就不处理

 

2注销:unRegister(this)方法,会以注册类为键 从typesBySubscriber里面获取值(map对象);返回一个集合如果集合不为空,就遍历集合,调用unsubscribeByEventType(subscriber, eventType)方法,通过注解方法参数类型作为键从subscriptionsByEventType获取值(map对象);值是个集合,再遍历集合删除集合所有数据。

注销方法最后调用typesBySubscriber.remove(subscriber)方法,就是以注册类为键删除对应保存在map中的值(注解方法参数类型集合)。

//注解也很简单,就是删除map的中注册类对应信息

 

3订阅消息:使用了自定义注解 ,这个不了解自定义注解的可以百度了解,这里简单介绍下

 

@Documented//表明这个注解应该被 javadoc工具记录
@Retention(RetentionPolicy.RUNTIME)//设置注解运行环境 这个设置运行时环境
@Target({ElementType.METHOD})//注解使用在什么上这个是设置可以使用在方法上
public @interface Subscribe {

   //ThreadMode threadMode()为注解参数   default为默认值
    ThreadMode threadMode() default ThreadMode.POSTING;


    boolean sticky() default false;

 
    int priority() default 0;
}

4发送消息:post();调用currentPostingThreadState.get()方法,返回PostingThreadState对象,(currentPostingThreadState其实是个threadlocal对象,通过threadlocal解决多线程并发问题) 通过PostingThreadState对象获取一个list集合对象eventQueue,把发送消息对象放进集合,并且把当前线程状态保存到postingState的isMainThread对象里面;最终调用postSingleEvent()这个方法主要是通过 发送的信息对象作为键从eventTypesCache(map对象)获取 注解参数类型集合;再遍历这个集合,在遍历方法里面调用postSingleEventForEventType(event, postingState, clazz),这个方法主要:以发送消息对象类型为键从subscriptionsByEventType获取以Subscription对象的集合(subscriptionsByEventType这个对象其实就是注册时的map对象);再遍历返回的集合(subscriptions)调用postToSubscription(subscription, event, postingState.isMainThread)方法;

这个方法主要判断注解方法设置的线程类型:例如设置的是默认线程 调invokeSubscriber(subscription, event)方法

这个方法里面其实就是利用反射给注解方法赋值

//这里线程切主要是靠Poster对象,跟踪源码这个类是MainThreadSupport类的内部类,通过调用createPoster()方法创建,这个类初始化是创建了HandlerPoster这个类,这个类继承handler 实现了poster接口;实际线程切换就是HandlerPoster这个类实现,其实就是通过handler实现线程切换; 最终还是调用invokeSubscriber(subscription, event)方法

 

 

 

 

 

//发送消息其实也就是通过发送的消息对象,从map获取消息对象类型集合;再通过消息对象类型从注册时的subscriptionsByEventType获取方法信息集合,获取注解方法,最总把发送的消息以反射方法赋值到注解方法里面。

 

//这里我手写了一个简易版EventBus,源码地址https://github.com/zhudaihao/MyEventBus

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值