EventBus使用及源码解析Word文档下载推荐.docx
- 文档编号:22100439
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:21
- 大小:350.09KB
EventBus使用及源码解析Word文档下载推荐.docx
《EventBus使用及源码解析Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《EventBus使用及源码解析Word文档下载推荐.docx(21页珍藏版)》请在冰豆网上搜索。
publicstaticEventBusgetDefault(){
if(defaultInstance==null){
synchronized(EventBus.class){
defaultInstance=newEventBus();
}
returndefaultInstance;
}
2.2.2NewEventBus
publicEventBus(){
this(DEFAULT_BUILDER);
在这里有调用了另外一个构造函数完成相关属性的初始化
EventBus(EventBusBuilderbuilder){
subscriptionsByEventType=newHashMap<
>
();
typesBySubscriber=newHashMap<
stickyEvents=newConcurrentHashMap<
mainThreadPoster=newHandlerPoster(this,Looper.getMainLooper(),10);
backgroundPoster=newBackgroundPoster(this);
asyncPoster=newAsyncPoster(this);
indexCount=builder.subscriberInfoIndexes!
=null?
builder.subscriberInfoIndexes.size():
0;
subscriberMethodFinder=newSubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification,builder.ignoreGeneratedIndex);
logSubscriberExceptions=builder.logSubscriberExceptions;
logNoSubscriberMessages=builder.logNoSubscriberMessages;
sendSubscriberExceptionEvent=builder.sendSubscriberExceptionEvent;
sendNoSubscriberEvent=builder.sendNoSubscriberEvent;
throwSubscriberException=builder.throwSubscriberException;
eventInheritance=builder.eventInheritance;
executorService=builder.executorService;
DefaultBuilder就是一个默认的EventBusBuilder;
有了EventBus实例就可以进行注册了,
publicvoidregister(Objectsubscriber){
//得到当前注册类的class对象;
Class<
?
subscriberClass=subscriber.getClass();
//根据Class查找当前类中订阅事件方法的集合,即使用了@Subcribe注解,有public修饰符
、一个参数的方法;
//SubscriberMethod类主要封装了符合条件方法的相关信息
//Method对象、线程模式、事件类型、优先级、是否粘性事件等;
List<
SubscriberMethod>
subscriberMethods=subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized(this){
//循环遍历了订阅了事件的方法的集合,以完成注册
for(SubscriberMethodsubscriberMethod:
subscriberMethods){
subscribe(subscriber,subscriberMethod);
2.2.3Registe
register方法主要分成两部分:
查找和注册:
首先看查找部分的代码:
List<
findSubscriberMethods(Class<
subscriberClass){
//METHOD_CACHE是一个ConcurrentHashMap,直接保存了subscriberClass和对应SubscriberMethod的集合,以提高注册效率,赋值重复查找。
subscriberMethods=METHOD_CACHE.get(subscriberClass);
if(subscriberMethods!
=null){
returnsubscriberMethods;
//由于使用了默认的EventBusBuilder,则ignoreGeneratedIndex属性默认为false,即是否忽略注解生成器
if(ignoreGeneratedIndex){
subscriberMethods=findUsingReflection(subscriberClass);
}else{
subscriberMethods=findUsingInfo(subscriberClass);
//如果对应类中没有符合条件的方法,则抛出异常
if(subscriberMethods.isEmpty()){
thrownewEventBusException("
Subscriber"
+subscriberClass
+"
anditssuperclasseshavenopublicmethodswiththe@Subscribeannotation"
);
//保存查找到的订阅事件的方法
METHOD_CACHE.put(subscriberClass,subscriberMethods);
2.2.3.1FindSubscriberMethod
该方法很清晰,先从缓存中查找,如果找到直接返回,否则去做下一步的查找过程,然后缓存查找到的集合,FindUsingInfo方法会被调用。
privateList<
findUsingInfo(Class<
FindStatefindState=prepareFindState();
findState.initForSubscriber(subscriberClass);
//初始状态下findState.clazz就是subscriberClass
while(findState.clazz!
findState.subscriberInfo=getSubscriberInfo(findState);
//条件不成立
if(findState.subscriberInfo!
SubscriberMethod[]array=findState.subscriberInfo.getSubscriberMethods();
array){
if(findState.checkAdd(subscriberMethod.method,subscriberMethod.eventType)){
findState.subscriberMethods.add(subscriberMethod);
//通过反射查找订阅事件的方法
findUsingReflectionInSingleClass(findState);
//修改findState.clazz为subscriberClass的父类Class,即需要遍历父类
findState.moveToSuperclass();
//查找到的方法保存在了FindState实例的subscriberMethods集合中。
//使用subscriberMethods构建一个新的List<
//释放掉findState
returngetMethodsAndRelease(findState);
2.2.3.2FindUsingInfo
该方法会在当前类及父类查找订阅事件的方法,这里还引用了一个FindState静态内部类,用来辅助查找订阅事件的方法,具体的查找过程在findUsingReflectSingleClass()方法中,主要通过反射查找订阅事件;
privatevoidfindUsingReflectionInSingleClass(FindStatefindState){
Method[]methods;
try{
//ThisisfasterthangetMethods,especiallywhensubscribersarefatclasseslikeActivities
methods=findState.clazz.getDeclaredMethods();
}catch(Throwableth){
//Workaroundforjava.lang.NoClassDefFoundError,see
methods=findState.clazz.getMethods();
findState.skipSuperClasses=true;
//循环遍历当前类的方法,筛选出符合条件的
for(Methodmethod:
methods){
//获得方法的修饰符
intmodifiers=method.getModifiers();
//如果是public类型,但非abstract、static等
if((modifiers&
Modifier.PUBLIC)!
=0&
&
(modifiers&
MODIFIERS_IGNORE)==0){
//获得当前方法所有参数的类型
Class<
[]parameterTypes=method.getParameterTypes();
//如果当前方法只有一个参数
if(parameterTypes.length==1){
SubscribesubscribeAnnotation=method.getAnnotation(Subscribe.class);
//如果当前方法使用了Subscribe注解
if(subscribeAnnotation!
//得到该参数的类型
eventType=parameterTypes[0];
//checkAdd()方法用来判断FindState的anyMethodByEventTypemap是否已经添加过以当前
eventType为key的键值对,没添加过则返回true
if(findState.checkAdd(method,eventType)){
//得到Subscribe注解的threadMode属性值,即线程模式
ThreadModethreadMode=subscribeAnnotation.threadMode();
//创建一个SubscriberMethod对象,并添加到subscriberMethods集合
findState.subscriberMethods.add(newSubscriberMethod(method,eventType,threadMode,
subscribeAnnotation.priority(),subscribeAnnotation.sticky()));
}elseif(strictMethodVerification&
method.isAnnotationPresent(Subscribe.class)){
StringmethodName=method.getDeclaringClass().getName()+"
."
+method.getName();
@Subscribemethod"
+methodName+
"
musthaveexactly1parameterbuthas"
+parameterTypes.length);
thrownewEventBusException(methodName+
isaillegal@Subscribemethod:
mustbepublic,non-static,andnon-abstract"
到此register()方法中findSubscriberMethods()流程就分析完了,已经找到当前注册类及其父类订阅事件方法的集合,下面是具体的注册流程,即register的subscriber()方法。
2.2.3.3subscriber()方法
privatevoidsubscribe(Objectsubscriber,SubscriberMethodsubscriberMethod){
//得到当前订阅了事件的方法的参数类型
eventType=subscriberMethod.eventType;
//Subscription类保存了要注册的类对象以及当前的subscriberMethod
SubscriptionnewSubscription=newSubscription(subscriber,subscriberMethod);
//subscriptionsByEventType是一个HashMap,保存了以eventType为key,Subscription对象集合为value的键值对
//先查找subscriptionsByEventType是否存在以当前eventType为key的值
CopyOnWriteArrayList<
Subscription>
subscriptions=subscriptionsByEventType.get(eventType);
if(subscriptions==null){
subscriptions=newCopyOnWriteArrayList<
subscriptionsByEventType.put(eventType,subscriptions);
if(subscriptions.contains(newSubscription)){
+subscriber.getClass()+"
alreadyregisteredtoevent"
+eventType);
//添加上边创建的newSubscription对象到subscriptions中
intsize=subscriptions.size();
for(inti=0;
i<
=size;
i++){
if(i==size||subscriberMethod.priority>
subscriptions.get(i).subscriberMethod.priority){
subscriptions.add(i,newSubscription);
break;
//typesBySubscribere也是一个HashMap,保存了以当前要注册类的对象为key,
//注册类中订阅事件的方法的参数类型的集合为value的键值对
//查找是否存在对应的参数类型集合
subscribedEvents=typesBySubscriber.get(subscriber);
if(subscribedEvents==null){
//不存在则创建一个subscribedEvents,并保存到typesBySubscriber
subscribedEvents=newArrayList<
typesBySubscriber.put(subscriber,subscribedEvents);
//保存当前订阅了事件的方法的参数类型
subscribedEvents.add(eventType);
if(subscriberMethod.sticky){
if(eventInheritance){
//ExistingstickyeventsofallsubclassesofeventTypehavetobeconsidered.
//Note:
Iteratingoveralleventsmaybeinefficientwithlotsofstickyevents,
//thusdatastructureshouldbechangedtoallowamoreefficientlookup
//(e.g.anadditionalmapstoringsubclassesofsuperclasses:
Class->
Class>
).
Set<
Map.Entry<
Object>
entries=stickyEvents.entrySet();
for(Map.Entry<
entry:
entries){
candidateEventType=entry.getKey();
if(eventType.isAssignableFrom(candidateEventType)){
ObjectstickyEvent=entry.getValue();
checkPostStickyEventToSubscription(newSubscription,stickyEvent);
ObjectstickyEvent=stickyEvents.get(eventType);
Subscriber()方法主要是为了得到subscriptionsByEventType、TypesBySubscriber两个HashMap,在发送事件时要用到subscriptionsByEventType,完成时间的处理,当取消EventBus注册时则要用到TypesBySubscriber、subscriptionsByEventType完成相关资源的释放;
下面是取消注册:
EventBus.getDefault.unRegister(this),其核心的方法就是unsubscriberByEventType();
publicsynchronizedvoidunregister(Objectsubscriber){
//得到当前注册类对象对应的订阅事件方法的参数类型的集合
subscribedTypes=typesBySubscriber.get(subscriber);
if(subscribedTypes!
//遍历参数类型集合,释放之前缓存的当前类中的Subscription
for(Class<
eventType:
subscribedTypes){
unsubscribeByEventType(subscriber,eventType);
//删除以subscriber为key的键值对
typesBySubscriber.remove(subscriber);
Log.w(TAG,"
Subscribertounregisterwasnotregisteredbefore:
+subscriber.getClass());
然后再看下unsubscribe
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- EventBus 使用 源码 解析