当前位置: 首页 > news >正文

电子商务网站建设与管理实训报告百度权重划分等级

电子商务网站建设与管理实训报告,百度权重划分等级,杭州seo,wordpress侧边栏在哪简介 前面我学习了如何使用EventBus#xff0c;还有了解了EventBus的特性#xff0c;那么接下来我们一起来学习EventBus的源码#xff0c;查看EventBus的源码#xff0c;看看EventBus给我们带来什么惊喜以及编程思想。 这个图我们从一开始就一直放置在上面了。我们在来回顾… 简介 前面我学习了如何使用EventBus还有了解了EventBus的特性那么接下来我们一起来学习EventBus的源码查看EventBus的源码看看EventBus给我们带来什么惊喜以及编程思想。 这个图我们从一开始就一直放置在上面了。我们在来回顾一下EventBus的官网是怎么定义它的呢EventBus是Android和Java的发布/订阅观察者模式事件总线。我们大概了解了EventBus的构建思想。接下来我们进入源码学习吧。 进入源码分析 我们从EventBus的注册开始入手。 EventBus.getDefault().register(this); public static EventBus getDefault() {if (defaultInstance null) {synchronized (EventBus.class) {if (defaultInstance null) {//创建了EventBus实例进入下面的方法defaultInstance new EventBus(); }}}return defaultInstance;} 上面的方法是一个双重校验的单例。 public EventBus() {this(DEFAULT_BUILDER); //private static final EventBusBuilder DEFAULT_BUILDER new EventBusBuilder();} DEFAULT_BUILDER是EventBusBuilder.class实例来创建的这个类非常重要使用自定义参数创建EventBus实例还允许自定义默认EventBus实例如前面的例子使用索引、配置EventBus的配置事件的优先级使用索引(四)等就是通过这个类来实现的大家可以回顾一下。进入初始化一下必要的参数的构造方法EventBus(EventBusBuilder builder),如下 EventBus(EventBusBuilder builder) {logger builder.getLogger(); /初始化LoggersubscriptionsByEventType new HashMap(); //存储订阅事件的typesBySubscriber new HashMap(); //存储相关订阅者class列表key是注册者的对象value是订阅者的class列表stickyEvents new ConcurrentHashMap(); //粘性事件//下面这4个实例就是我们设置方法threadMode ThreadMode.xxx//*1mainThreadSupport builder.getMainThreadSupport();mainThreadPoster mainThreadSupport ! null ? mainThreadSupport.createPoster(this) : null;backgroundPoster new BackgroundPoster(this);asyncPoster new AsyncPoster(this);//获取注册者信息索引(添加由EventBus的注释预处理器生成的索引)indexCount builder.subscriberInfoIndexes ! null ? builder.subscriberInfoIndexes.size() : 0;//初始订阅方法查找器。这个类主要具有查找订阅的方法继续往下看subscriberMethodFinder new SubscriberMethodFinder(builder.subscriberInfoIndexes,builder.strictMethodVerification, builder.ignoreGeneratedIndex);logSubscriberExceptions builder.logSubscriberExceptions; //是否有日记订阅默认truelogNoSubscriberMessages builder.logNoSubscriberMessages;//是否有日记信息默认 truesendSubscriberExceptionEvent builder.sendSubscriberExceptionEvent;//是否发送订阅异常事件默认truesendNoSubscriberEvent builder.sendNoSubscriberEvent; //是否发送没有订阅事件默认truethrowSubscriberException builder.throwSubscriberException; //是否抛出异常处理//默认情况下EventBus会考虑事件类层次结构将通知超类的注册者。 关闭此功能将改善事件的发布。对于直接扩展Object的简单事件类我们测量事件发布的速度提高了20。eventInheritance builder.eventInheritance; executorService builder.executorService; //创建线程池} 我们将此段代码逐步分析.这步主要是进行初始化话一下必要的参数如代码注解所示。下面这段代码就是我们常用的Subscribe(threadMode ThreadMode.xxx);初始化。一般常用的就是以下4种。 mainThreadSupport builder.getMainThreadSupport(); mainThreadPoster mainThreadSupport ! null ? mainThreadSupport.createPoster(this) : null; backgroundPoster new BackgroundPoster(this); asyncPoster new AsyncPoster(this); 我们来看看builder.getMainThreadSupport()方法返回的是MainThreadSupport接口表示为支持Android主线程。上面的4个线程中都持有 PendingPostQueue 等待发送的队列实例。由mainThreadSupport.createPoster(this)创建一个HandlerPoster而该类继承了Handle并且初始化了一个等待发布队列。代码如下。 public interface MainThreadSupport {boolean isMainThread();Poster createPoster(EventBus eventBus);class AndroidHandlerMainThreadSupport implements MainThreadSupport {private final Looper looper;public AndroidHandlerMainThreadSupport(Looper looper) {this.looper looper;}Overridepublic boolean isMainThread() {return looper Looper.myLooper();}Overridepublic Poster createPoster(EventBus eventBus) {return new HandlerPoster(eventBus, looper, 10);}} } subscriberMethodFinder new SubscriberMethodFinder(builder.subscriberInfoIndexes,builder.strictMethodVerification, builder.ignoreGeneratedIndex); 上面代码在这里主要初始化订阅的方法查找器。下面会讲解到它是如何进行订阅方法的。我们这这里知道了EventBus初始化然后相关的实例的创建接下来我我们进入到register(this)方法的调用如下方法。 public void register(Object subscriber) {//获取当前注册者对象的Class。Class? subscriberClass subscriber.getClass(); //通过该注册者的Class来获取当前注册者里面由Subscriber注解绑定的方法。ListSubscriberMethod subscriberMethods subscriberMethodFinder.findSubscriberMethods(subscriberClass);//必须在线程同步中进行。synchronized (this) {for (SubscriberMethod subscriberMethod : subscriberMethods) {subscribe(subscriber, subscriberMethod);}}} 上面的代码表示的是给注册者接收事件。 传递当前所注册的对象如Activity、Fragment。 注意 注册者如果不再接收信息必须调用unregister(Object)方法表示解除注册则该订阅者将不再接收到数据了如果不进行解除将可能出现内存泄漏。一般在onDestroy方法解除注册后面会讲解到。 在注册者中拥有必须由Subscribe注解的方法。Subscribe还允许配置ThreadMode和优先级、是否是粘性行为。接着我们进入ListSubscriberMethod subscriberMethods subscriberMethodFinder.findSubscriberMethods(subscriberClass);方法。 //private static final MapClass?, ListSubscriberMethod METHOD_CACHE new ConcurrentHashMap(); //线程安全ListSubscriberMethod findSubscriberMethods(Class? subscriberClass) {//从Map集合中获取订阅方法列表ListSubscriberMethod subscriberMethods METHOD_CACHE.get(subscriberClass);//判断当前获取方法是否为空if (subscriberMethods ! null) {return subscriberMethods;}//通过EventBusBuilder.ignoreGeneratedIndex//是否忽略配置索引默认是忽略索引if (ignoreGeneratedIndex) {//1.通过反射获取方法列表subscriberMethods findUsingReflection(subscriberClass);} else {//2.通过索引方式获取订阅方法列表subscriberMethods findUsingInfo(subscriberClass);}//是否订阅方法为空如果为空则表示该订阅者里面的方法都不符合EventBus订阅方法的规则if (subscriberMethods.isEmpty()) {throw new EventBusException(Subscriber subscriberClass and its super classes have no public methods with the Subscribe annotation);} else {//存储到集合中METHOD_CACHE.put(subscriberClass, subscriberMethods);return subscriberMethods;} } 我们逐步分析该段代码。该段代码通过注册者的类来获取当前dingy的方法列表如果不为空则直接返回订阅方法。通过反射来查找订阅方法如果该方法为空则抛出异常该订阅者的方法和其超类没有Subscriber注解的共有方法即表示不符合EventBus订阅方法的规则。如果不为空则存储到ConcurrentHashMap集合中。这里的是由ConcurrentHashMap集合存储是以当前订阅者的class为key而将其由Subscriber绑定的方法添加到List中,就是集合的value。必须保持线程安全的所以这里使用了ConcurrentHashMap。 1.是否忽略索引设置该方法表示忽略设置索引,进入该方法findUsingReflection(Class? subscriberClass)通过反射进行获取ListSubscriberMethod注设置索引在EventBus的配置事件的优先级使用索引(四)这里说的大家可以去看看。private ListSubscriberMethod findUsingReflection(Class? subscriberClass) {FindState findState prepareFindState();//准备查找状态findState.initForSubscriber(subscriberClass);// 初始化订阅者信息while (findState.clazz ! null) {//循环获取订阅者的class是否为空//通过反射获取订阅方法// 3.该方法下面分析findUsingReflectionInSingleClass(findState); findState.moveToSuperclass(); //删除超类class}获取订阅方法listreturn getMethodsAndRelease(findState);} 上面的代码主要是通过反射来获取相关的订阅方法里面由静态内部类FindState进行管理相关信息由于上面的方法和下面索引的方法都将调用同一个方法所以放在下面来将讲解请看下面信息。 2.是否忽略索引设置该方法表示的设置了索引进入findUsingInfo(Class? subscriberClass)方法如下。private ListSubscriberMethod findUsingInfo(Class? subscriberClass) {FindState findState prepareFindState(); //准备查找状态findState.initForSubscriber(subscriberClass);// 初始化订阅者信息while (findState.clazz ! null) { //循环获取订阅者的class是否为空findState.subscriberInfo getSubscriberInfo(findState);//获取获取订阅者信息这里如果使用添加索引的话这里将能获取到索引的相关信息。if (findState.subscriberInfo ! null) { //获取订阅方法SubscriberMethod[] array findState.subscriberInfo.getSubscriberMethods();for (SubscriberMethod subscriberMethod : array) {//进行等级检查并存储到Map集合中该方法checkAdd是FindState.class中的方法 key是Subscriber中参数的classvalue是该subscriberMethod.method也就是Subscribe中的方法如public void onMessageEvent(MessageEvent event)if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {//将该订阅方法添加到列表中findState.subscriberMethods.add(subscriberMethod);}}} else {//3.通过使用反射的方式来获取和上面忽略索引调用到同一个方法这里将解析findUsingReflectionInSingleClass(findState);}//清除父类的方法findState.moveToSuperclass();}//获取订阅方法listreturn getMethodsAndRelease(findState);} 分析本段代码。首先进入查找的准备状态通过默认状态池返回状态信息主要存储的是FindState实例。主要存储的有订阅者的class、订阅者信息SubscriberInfo。订阅者Subscribe方法列表ListSubscriberMethod等.如果当前订阅者class不为空则将获取到订阅者信息。这里分两种情况。如果使用添加索引的话getSubscriberInfo(findState)该方法将获取到订阅信息如果没有使用索引的话则将调用findUsingReflectionInSingleClass(findState);该方法来获取信息 使用添加索引并返回订阅方法该方法如下 //获取订阅方法SubscriberMethod[] array findState.subscriberInfo.getSubscriberMethods(); 由于AbstractSubscriberInfo类实现了SubscriberInfo接口而SimpleSubscriberInfo继承了AbstractSubscriberInfo并实现了getSubscriberMethods方法代码如下本段代码在SimpleSubscriberInfo.class中。返回订阅方法数组SubscriberMethod[]。 Overridepublic synchronized SubscriberMethod[] getSubscriberMethods() {int length methodInfos.length;SubscriberMethod[] methods new SubscriberMethod[length];for (int i 0; i length; i) {SubscriberMethodInfo info methodInfos[i];methods[i] createSubscriberMethod(info.methodName, info.eventType, info.threadMode,info.priority, info.sticky);}return methods;} 3.如果没有添加索引则进入该方法findUsingReflectionInSingleClass(findState);通过反射来获取订阅者方法。这个方法有点长慢慢看。 private void findUsingReflectionInSingleClass(FindState findState) {Method[] methods;try {// This is faster than getMethods, especially when subscribers are fat classes like Activities//该方法代替getMethods()方法获取该订阅者class全部方法。methods findState.clazz.getDeclaredMethods();} catch (Throwable th) {// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149methods findState.clazz.getMethods(); //获取该订阅者class全部方法findState.skipSuperClasses true; //设置跳过超类}for (Method method : methods) {int modifiers method.getModifiers();//获取修饰符if ((modifiers Modifier.PUBLIC) ! 0 (modifiers MODIFIERS_IGNORE) 0) { //通过与运算判断当前的修饰符是否符合EventBus方法定义Class?[] parameterTypes method.getParameterTypes(); //获取参数类型if (parameterTypes.length 1) { //因为EventBus方法中必须有参数所以当参数为1时符合要求//通过注解的形式Subscribe获取Subscribe默认的Subscribe为(priority0,stickyfalse,threadModePOSTING),就是说ThreadMode为POSTING粘性为false优先级为0,如果方法中设置了相应的值则将是你设置的值。如threadModeMAIN。Subscribe subscribeAnnotation method.getAnnotation(Subscribe.class);if (subscribeAnnotation ! null) {Class? eventType parameterTypes[0]; //获取当前参数的class//进行等级检查并存储到Map集合中该方法checkAdd是FindState.class中的方法 key是Subscriber中参数的classvalue是该subscriberMethod.method也就是Subscribe中的方法如public void onMessageEvent(MessageEvent event)if (findState.checkAdd(method, eventType)) { // 获取ThreadMode 如MAINThreadMode threadMode subscribeAnnotation.threadMode();//将订阅方法添加到列表中findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,subscribeAnnotation.priority(), subscribeAnnotation.sticky()));}}} else if (strictMethodVerification method.isAnnotationPresent(Subscribe.class)) { //不符合EventBus订阅方法的规则要求。抛出异常提示该方法必须是Subscribe注解并且需要一个参数String methodName method.getDeclaringClass().getName() . method.getName();throw new EventBusException(Subscribe method methodName must have exactly 1 parameter but has parameterTypes.length);}} else if (strictMethodVerification method.isAnnotationPresent(Subscribe.class)) {//是一种非法的Subscribe方法必须是公共的非静态的非抽象的String methodName method.getDeclaringClass().getName() . method.getName();throw new EventBusException(methodName is a illegal Subscribe method: must be public, non-static, and non-abstract);}}} 该段代码主要是获取该注册者的全部方法并进行筛选出来符合EventBus的订阅方法的规则通过注解的形式来获取订阅方法最后添加到查找状态的列表中。首先获取的是修饰符参数类型再通过注解的形式来获取订阅方法。如下注解Subscribe 如果不符合EventBus相关订阅方法的规则将抛出异常提示是否在方法上书写了错误的方法。接下来我们进入看看Subscribe 订阅方法是通过注解的形式来设置的。 Documented Retention(RetentionPolicy.RUNTIME) Target({ElementType.METHOD}) public interface Subscribe {//ThreadMode 默认POSTINGThreadMode threadMode() default ThreadMode.POSTING;//粘性事件默认falseboolean sticky() default false;//优先级默认0int priority() default 0; } 接下来进入getMethodsAndRelease(FindState findState) private ListSubscriberMethod getMethodsAndRelease(FindState findState) {//获取到订阅方法列表ListSubscriberMethod subscriberMethods new ArrayList(findState.subscriberMethods); findState.recycle(); //清空回收相关信息synchronized (FIND_STATE_POOL) {for (int i 0; i POOL_SIZE; i) {if (FIND_STATE_POOL[i] null) {FIND_STATE_POOL[i] findState; //将查找状态器findState添加到状态池FIND_STATE_POOL中为下次直接从查找状态池中获取break;}}}return subscriberMethods; // 返回订阅方法列表} 上面该方法通过FindState静态内部类获取了订阅的列表然后被存储到了ConcurrentHashMap集合中。并且存储到状态池中为方便下次读取。并且回收资源。获取到ListSubscriberMethod订阅列表后再次回到了注册方法中register(Object subscriber)进入到方法subscribe(subscriber, subscriberMethod);该方法通过循环进行遍历 注 此处必须是在线程同步中进行所以添加synchronized。//这里的参数subscriber表示的是订阅者如Activity等subscriberMethod表示订阅方法该方法就是在subscriber里面 private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {Class? eventType subscriberMethod.eventType; //获取事件类型也就是参数的classSubscription newSubscription new Subscription(subscriber, subscriberMethod);//通过事件类型参数class获取CopyOnWriteArrayListSubscription列表该类大家可以研究一下//是写时复制容器即当我们往CopyOnWriteArrayList容器添加元素时先从原有的数组中拷贝一份出来然后在新的容器做写操作(添加元素)写完之后再将原来的数组引用指向到新数组的形式存储数据的它是线程安全的。CopyOnWriteArrayListSubscription subscriptions subscriptionsByEventType.get(eventType);if (subscriptions null) {subscriptions new CopyOnWriteArrayList();subscriptionsByEventType.put(eventType, subscriptions); //添加到Map集合中} else {if (subscriptions.contains(newSubscription)) { //是否已经存在了throw new EventBusException(Subscriber subscriber.getClass() already registered to event eventType);}}int size subscriptions.size();for (int i 0; i size; i) {if (i size || subscriberMethod.priority subscriptions.get(i).subscriberMethod.priority) { //判断优先级subscriptions.add(i, newSubscription);//优先级高的添加添加到CopyOnWriteArrayList容器最前面只有一个的时候就是添加在第一位了。break;}}//获取订阅事件的class列表即订阅方法的参数class列表ListClass? subscribedEvents typesBySubscriber.get(subscriber);if (subscribedEvents null) {subscribedEvents new ArrayList();//存储到Map集合key是订阅者(即上面传递的Activity对象)value是订阅事件列表typesBySubscriber.put(subscriber, subscribedEvents);}subscribedEvents.add(eventType); //将该事件类型class添加到订阅事件列表中判断当前方法是否是粘性的if (subscriberMethod.sticky) {if (eventInheritance) {//必须考虑eventType的所有子类的现有粘性事件// Existing sticky events of all subclasses of eventType have to be considered.// Note: Iterating over all events may be inefficient with lots of sticky events,// thus data structure should be changed to allow a more efficient lookup// (e.g. an additional map storing sub classes of super classes: Class - ListClass).SetMap.EntryClass?, Object entries stickyEvents.entrySet();for (Map.EntryClass?, Object entry : entries) {Class? candidateEventType entry.getKey();isAssignableFrom(Class? cls)方法表示的类型是否可以通过标识转换或通过扩展引用转换为此类对象表示的类型则返回trueif (eventType.isAssignableFrom(candidateEventType)) {Object stickyEvent entry.getValue();//将粘性事件添加到订阅者列表中checkPostStickyEventToSubscription(newSubscription, stickyEvent);}}} else {//将粘性事件添加到订阅者列表中Object stickyEvent stickyEvents.get(eventType);checkPostStickyEventToSubscription(newSubscription, stickyEvent);}}} 上面的方法中主要是通过获取事件类型即订阅方法中的参数class。然后将其添加到Map集合中这里用到了CopyOnWriteArrayList(原理是写时复制容器即当我们往CopyOnWriteArrayList容器添加元素时先从原有的数组中拷贝一份出来然后在新的容器做写操作(添加元素)写完之后再将原来的数组引用指向到新数组的形式存储数据的它是线程安全的。) 然后进行判断是否设置优先级遍历并添加到subscriptions列表中。通过当前的注册者获取注册者class列表并添加到typesBySubscriber集合中key是注册者的class如Activity而value就是订阅方法中的参数class的列表。这个地方说明了一个注册者可以拥有多个订阅事件(方法)将其绑定起来存储到Map集合中。最后将该参数class添加到subscribedEvents.add(eventType);列表中。下面方法是检查粘性事件订阅发送事件方法如下 private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {if (stickyEvent ! null) {// If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)// -- Strange corner case, which we dont take care of here.//这段代码我们到post发送事件的调用的时候讲解。postToSubscription(newSubscription, stickyEvent, isMainThread());}} 注这里主要是检查是否发送粘性发送事件方法 postToSubscription我们到发送事件POST方法调用时讲解。事件发送接下来我进入post方法事件发送。此时我们回忆一下简介中的图post()EventBus将分发到各个订阅事件中。也就是订阅方法。我们来看看是如何进行操作的。代码如下 EventBus.getDefault().post(new MessageEvent(message)); 通过以上代码我大概的知道post()方法里面的参数是一个实体的对象而该实体就是我们在订阅方法中的参数实体。你发现了什么了吗前边我们已经分析了该注册者的订阅方法主要的存储过程接下来我们一起进入探究吧。方法跟踪进入post()方法。 /** Posts the given event to the event bus. *///给订阅事件发送事件总线public void post(Object event) {//获取当前线程即通过ThreadLocal本地线程来管理对应的事件线程并且初始化发送线程状态PostingThreadStatePostingThreadState postingState currentPostingThreadState.get();ListObject eventQueue postingState.eventQueue; eventQueue.add(event); //添加到事件队列中//判断当前发送线程状态是否是正在发送的事件if (!postingState.isPosting) {postingState.isMainThread isMainThread();postingState.isPosting true;if (postingState.canceled) {throw new EventBusException(Internal error. Abort state was not reset);}try {while (!eventQueue.isEmpty()) {//发送事件发送完一个删除一个直到发送全部停止循环postSingleEvent(eventQueue.remove(0), postingState);}} finally {//设置标志改变postingState.isPosting false;postingState.isMainThread false;}}} currentPostingThreadState.get()方法中我们知道 private final ThreadLocalPostingThreadState currentPostingThreadState new ThreadLocalPostingThreadState() {Overrideprotected PostingThreadState initialValue() {return new PostingThreadState();}}; 通过ThreadLocal这里就叫本地线程吧来管理当前的发送线程状态每个发送线程将得到对应一个PostingThreadState而该PostingThreadState管理eventQueue信息该信息主要存储的是发送事件。通过eventQueue.add(event)存储该发送事件以后完成以后就判断当前的发送事件状态是否是正在发送中如果还没发送则当该eventQueue不为为空的时候进入循环发送该事件发送完一个就删除一个直到发送完成为止。进入方法postSingleEvent(Object event, PostingThreadState postingState)中。 private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {Class? eventClass event.getClass();boolean subscriptionFound false;if (eventInheritance) {//查找所有事件类型ListClass? eventTypes lookupAllEventTypes(eventClass);int countTypes eventTypes.size();for (int h 0; h countTypes; h) {Class? clazz eventTypes.get(h);//发送事件subscriptionFound | postSingleEventForEventType(event, postingState, clazz);}} else {subscriptionFound postSingleEventForEventType(event, postingState, eventClass);}if (!subscriptionFound) {if (logNoSubscriberMessages) {logger.log(Level.FINE, No subscribers registered for event eventClass);}if (sendNoSubscriberEvent eventClass ! NoSubscriberEvent.class eventClass ! SubscriberExceptionEvent.class) {post(new NoSubscriberEvent(this, event));}}} 上面的方法首先获取该事件类型的class然后传递到lookupAllEventTypes(eventClass)方法中通过该方法获取当前发送事件的class包括父类、实现的接口等等列表。所以一般情况下会返回当前发送的事件和Object.class(注当然了如果该事件实现接口的话也会包括实现的接口的。)列表即ListClass?然后进行遍历进行或运算。我们先进入lookupAllEventTypes(eventClass)方法看看返回的事件类型并且知道他存储到Map集合中即key是当前事件classvalue是该事件的所有类型包括父类接口等。 /** Looks up all Class objects including super classes and interfaces. Should also work for interfaces. */private static ListClass? lookupAllEventTypes(Class? eventClass) {//private static final MapClass?, ListClass? eventTypesCache new HashMap(); key是当前事件类型的classvalu则是事件的所有类型包括父类接口等。本事例会得到的是MessageEvent.class、和Object.classsynchronized (eventTypesCache) {ListClass? eventTypes eventTypesCache.get(eventClass);if (eventTypes null) {eventTypes new ArrayList();Class? clazz eventClass;while (clazz ! null) {eventTypes.add(clazz); //添加到列表中//添加接口addInterfaces(eventTypes, clazz.getInterfaces());clazz clazz.getSuperclass(); //获取父类class}eventTypesCache.put(eventClass, eventTypes); //存储d}return eventTypes;}} 看看方法postSingleEventForEventType(event, postingState, clazz)发送事件 private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class? eventClass) {CopyOnWriteArrayListSubscription subscriptions;synchronized (this) {//通过当前的事件class获取订阅事件列表subscriptions subscriptionsByEventType.get(eventClass);}if (subscriptions ! null !subscriptions.isEmpty()) {for (Subscription subscription : subscriptions) {//对PostingThreadState进行赋值postingState.event event;postingState.subscription subscription;boolean aborted false;try {//发送事件postToSubscription(subscription, event, postingState.isMainThread);aborted postingState.canceled;} finally {//设置参数为空postingState.event null;postingState.subscription null;postingState.canceled false; //设置标志}if (aborted) {break;}}return true;}return false;} 大家是否还记得在注册的时候出现的CopyOnWriteArrayListSubscription在这里就用到了通过发送事件的class获取CopyOnWriteArrayList容器里面的订阅事件信息包括注册者对象订阅方法等。然后遍历并进行发送事件。在此方法发布postToSubscription()事件 /*** subscription发布订阅的事件处理器* event当前发布的事件* isMainThread是否是在主线程中*/ private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {switch (subscription.subscriberMethod.threadMode) {case POSTING:invokeSubscriber(subscription, event);break;case MAIN:if (isMainThread) {invokeSubscriber(subscription, event);} else {mainThreadPoster.enqueue(subscription, event);}break;case MAIN_ORDERED:if (mainThreadPoster ! null) {mainThreadPoster.enqueue(subscription, event);} else {// temporary: technically not correct as poster not decoupled from subscriberinvokeSubscriber(subscription, event);}break;case BACKGROUND:if (isMainThread) {backgroundPoster.enqueue(subscription, event);} else {invokeSubscriber(subscription, event);}break;case ASYNC:asyncPoster.enqueue(subscription, event);break;default:throw new IllegalStateException(Unknown thread mode: subscription.subscriberMethod.threadMode);}} 好了这就是之前我们在注册中有一个地方遗留下的就是判断是否是粘性状态是调用的方法大家往回看就看到了在方法checkPostStickyEventToSubscription中有调用到该方法。这里会根据在方法中所选的threadMode进行调用 1.MAIN,如果当前是否是UI线程则会进入到invokeSubscriber(subscription, event);方法中。否则将调用mainThreadPoster.enqueue(subscription, event);这个方法将交给HandlerPoster.class里面的enqueue(Subscription subscription, Object event)方法HandlerPoster.class现实了该接口移交给handle完成大家可以进入HandlerPoster.class看看这里就不说了。2.POSTING直接调用 invokeSubscriber(subscription, event); 3.MAIN_ORDERED如果当前mainThreadPoster不为空则调用 mainThreadPoster.enqueue(subscription, event);和MAIN进入HandlerPoster.class反之调用invokeSubscriber(subscription, event); 4.BACKGROUND如果当前是主线程则调用backgroundPoster.enqueue(subscription, event);,反之调用invokeSubscriber(subscription, event); 5.ASYNC,异步方法调用执行 asyncPoster.enqueue(subscription, event);方法进行跟踪该类有实现了Runnable接口然后调用eventBus.invokeSubscriber(pendingPost);最终将调用了invoke方法。void invokeSubscriber(Subscription subscription, Object event) {try {subscription.subscriberMethod.method.invoke(subscription.subscriber, event);} catch (InvocationTargetException e) {handleSubscriberException(subscription, event, e.getCause());} catch (IllegalAccessException e) {throw new IllegalStateException(Unexpected exception, e);}} invoke()这是一个本地的方法将调用C/C的到方法进行发布。最后将进入到订阅方法中。并传递该事件到到订阅的方法中。好了这里我们将post发布事件的方法简单的分析了一下。整个EventBus的分析差不多完成了但是我们还有一点不能忘记就是解除绑定。接下来我们来看看解除绑定的方法。 注该方法一般生命周期的onDestroy()方法中进行解除绑定。代码如下 EventBus.getDefault().unregister(this); 直接进入unregister(this) /** Unregisters the given subscriber from all event classes. */public synchronized void unregister(Object subscriber) {ListClass? subscribedTypes typesBySubscriber.get(subscriber);if (subscribedTypes ! null) {for (Class? eventType : subscribedTypes) {unsubscribeByEventType(subscriber, eventType);}typesBySubscriber.remove(subscriber);} else {logger.log(Level.WARNING, Subscriber to unregister was not registered before: subscriber.getClass());}} /** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. *//*** subscriber指代当前解除注册的对象如Activity* eventType发送的事件类型post函数的实体对象class*/ private void unsubscribeByEventType(Object subscriber, Class? eventType) {ListSubscription subscriptions subscriptionsByEventType.get(eventType);if (subscriptions ! null) {int size subscriptions.size();for (int i 0; i size; i) {Subscription subscription subscriptions.get(i);if (subscription.subscriber subscriber) {subscription.active false;subscriptions.remove(i); //删除i--; //目的是减少遍历次数size--;}}} } 解除绑定这里很简单。这里就不一一进行解释了^_^。 总结 1.本篇文章主要对EventBus源码进行简单的分析。主要是进行了观察者模式的一些高级运用。如果大家对观察者模式理解不怎么清楚可以进入这里看看简单的案例观察者模式内容非常简单。2.相关的EvenBut的使用请看之前的内容。如EventBus认识(一)、EventBus的ThreadMode使用以及分析(二)等等。3.学习本篇文章中可以认识到一些常用的类如CopyOnWriteArrayList、ThreadLocal等到时可以深入研究一下有助我们提高。4.一些编程思想设计模式值得我们去学习的如单例模式EventBus双重校验、建造者模式EventBus构造器的时候用到用了初始化各个参数等等。面向接口编程而不针对实现编程。5.如果有什么问题希望大家进行指正好好学习一起进步。
http://www.pierceye.com/news/891185/

相关文章:

  • 猎头网站模板济源专业网站建设(制作网站)
  • kotlin做网站单页应用网站
  • 邢台网站改版开发长沙教育网站开发
  • 网站开发人员必备技能网站背景图片自动切换
  • 企业网站建立策划书有网站吗给一个
  • 外贸建站有哪些公司建设主管部门网站查询
  • 泰安市网站建设广州优化公司哪家好
  • 手机网游传奇西安关键词优化平台
  • 网站建设公司权威机构3d虚拟人物制作软件
  • 北京网站建设seo公司哪家好阿里巴巴企业邮箱登录入口
  • 广州shopify代建站新产品代理
  • html5网站特点在线搜索引擎
  • 网站搭建服务平台网站备案 关闭网站
  • 高端建站收费标准宣传设计网站
  • 视频网站数据库设计手机企业网站设计
  • 广安发展建设集团有限公司门户网站竞价推广代运营服务
  • 济南mip网站建设公司山西住房建设厅网站
  • 兰州需要做网站的公司有哪些做词云的网站
  • 红酒公司网站建设模板6841如何通过网站获取qq
  • 写一张营销型网站页面多长时间微动漫怎么制作
  • 网站架构设计师月薪多少柳州团购网站建设
  • 深圳宝安沙井网站建设网络营销推广主要做什么?有哪些方法和技巧?
  • 图书馆门户网站建设的意义开票 网站建设
  • 如何用家用电脑做网站wordpress的伪静态
  • 东营市城市和建设管理局网站网络基础知识点
  • 怎么制作网站链接转发视频网页游戏开服表怎么取消
  • 360网站seo怎么做北京商场关闭通知
  • 连云港建设公司网站工程承包信息
  • 互动网站制作建设医院网站服务
  • 用asp做网站span增城高端网站建设