前言

上一篇文章自己对EventBus的用法进行了简单的叙述,然后自己又去研究了一下EventBus3.0源码也参考了网上的一些大佬的博客进行进一步的理解,写这一篇文章让自己对EventBus有个好的总结回顾,如有不正确的地方欢迎留言。

一、EventBus简介

在EventBus没出现之前,那时候的开发者一般是使用Android四大组件中的广播进行组件间的消息传递,那么我们为什么要使用事件总线机制来替代广播呢?主要是因为:

广播:耗时、容易被捕获(不安全)。
事件总线:更节省资源、更高效,能将信息传递给原生以外的各种对象。

关于事件其实是一个泛泛的统称,指的是一个概念上的东西(不一定非得用什么Event命),通过查阅官方文档,事件的命名格式并没有任何要求,你可以定义一个对象作为事件,也可以发送基本数据类型如int,String等作为一个事件。后续的源码也可以进步证明(方法的命名并没有任何要求,只是加上@Subscribe注解即可!同时事件的命名也没有任何要求)。

EventBus作为一个消息总线主要有三个组成部分:
事件(Event): 可以是任意类型的对象。通过事件的发布者将事件进行传递。
事件订阅者(Subscriber): 接收特定的事件。
事件发布者(Publisher): 用于通知 Subscriber 有事件发生。可以在任意线程任 意位置发送事件。
图1
上图1解释了整个EventBus的大概工作流程:事件的发布者(Publisher)将事件 (Event)通过post()方法发送。EventBus内部进行处理,找到订阅了该事件 (Event)的事件订阅者(Subscriber)。然后该事件的订阅者(Subscriber)通过 onEvent()方法接收事件进行相关处理。

二、EventBus源码解析

1、订阅者:EventBus.getDefault().register(this);

首先,我们从获取EventBus实例的方法getDefault()开始分析:

public static EventBus getDefault() {if (defaultInstance == null) {synchronized (EventBus.class) {if (defaultInstance == null) {defaultInstance = new EventBus();}}}return defaultInstance;
}

在getDefault()中使用了双重校验并加锁的单例模式来创建EventBus实例。
接着,我们看到EventBus的默认构造方法中做了什么:

private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();public EventBus() {this(DEFAULT_BUILDER);
}

在EventBus的默认构造方法中又调用了它的另一个有参构造方法,将一个类型为EventBusBuilder的DEFAULT_BUILDER对象传递进去了。这里的EventBusBuilder很明显是一个EventBus的建造器,以便于EventBus能够添加自定义的参数和安装一个自定义的默认EventBus实例。
我们再看一下EventBusBuilder的构造方法:

public class EventBusBuilder {...EventBusBuilder() {}...}

EventBusBuilder的构造方法中什么也没有做,那我么继续查看EventBus的这个有参构造方法:

private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;EventBus(EventBusBuilder builder) {...//Map<订阅事件, 订阅该事件的订阅者集合> 键为 Event的类类型(也就是定义订阅方法里面的实体类型),值为元素 Subscription(订阅信息)链表//Subscription 类:关注类中两个字段,一个是 Object 类型的 subscriber,该字段即为注册的对象(在 Android 中时常为 Activity) //另一个是 SubscriberMethod 类型,细节如下://subscriberMethod:SubscriberMethod 类型(订阅方法)。关注类中有个字段 eventType 是 Class<?> 类型,代表 Event 的类类型。subscriptionsByEventType = new HashMap<>();// Map<订阅者, 订阅事件集合> (举个例子就是Activity中对应着该Activity中所有的对应的订阅方法)typesBySubscriber = new HashMap<>();// Map<订阅事件类类型,订阅事件实例对象>. 专用于粘性事件处理的一个字,用于判断某个对象是否注册过.stickyEvents = new ConcurrentHashMap<>();//mainThreadPoster:主线程事件发送器,通过它的mainThreadPoster.enqueue(subscription, event)//方法可以将订阅信息和对应的事件进行入队,//然后通过 handler 去发送一个消息,在 handler 的 handleMessage 中去执行方法。 mainThreadSupport = builder.getMainThreadSupport();mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;//backgroundPoster:后台事件发送器,通过它的enqueue() 将方法加入到后台的一个队列,//最后通过线程池去执行,注意,它在 Executor的execute()方法 上添加了 synchronized关键字 //并设立了控制标记flag,保证任一时间只且仅能有一个任务会被线程池执行。backgroundPoster = new BackgroundPoster(this);//asyncPoster:实现逻辑类似于backgroundPoster,不同于backgroundPoster的保证//任一时间只且仅能有一个任务会被线程池执行的特性,asyncPoster则是异步运行的,可以同时接收多个任务asyncPoster = new AsyncPoster(this);...subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,builder.strictMethodVerification, builder.ignoreGeneratedIndex);// 从builder取中一些列订阅相关信息进行赋值...// 从builder中取出了一个默认的线程池对象,它由Executors的newCachedThreadPool()方法创建,它是一个有则用、无则创建、无数量上限的线程池。executorService = builder.executorService;
}

下面看具体的register()中执行的代码。

  public void register(Object subscriber) { //订阅者类型 Class<?> subscriberClass = subscriber.getClass(); //判断该类是不是匿名类,如果是匿名类要使用反射 boolean forceReflection = subscriberClass.isAnonymousClass(); //获取订阅者全部的响应函数信息(即上面的onNewsEvent()之类的方法) List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(sub scriberClass, forceReflection); //循环每一个事件响应函数,执行 subscribe()方法,更新订阅相关信息 for (SubscriberMethod subscriberMethod : subscriberMetho ds) { subscribe(subscriber, subscriberMethod); } }

接着我们查看SubscriberMethodFinder的findSubscriberMethods()方法:

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {// METHOD_CACHE:Map<Class<?>, List<SubscriberMethod>> 类型。键为注册类的 Class(例如:Activity),//值为该类中所有 EventBus 回调的方法链表(也就是被 @Subscribe 标记的方法们)。List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);if (subscriberMethods != null) {return subscriberMethods;}//ignoreGeneratedIndex 来判断是否使用生成的 APT 代码去优化寻找接收事件的过程,如果开启了的话,//那么将会通过 subscriberInfoIndexes 来快速得到接收事件方法的相关信息。//所以各位读者如果没有在项目中接入 EventBus 的 APT,//那么可以将 ignoreGeneratedIndex 设为 false 提高性能if (ignoreGeneratedIndex) {subscriberMethods = findUsingReflection(subscriberClass);} else {subscriberMethods = findUsingInfo(subscriberClass);}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;}
}

在这里我们假如ignoreGeneratedIndex为true,看下findUsingReflection()方法

private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {FindState findState = prepareFindState();findState.initForSubscriber(subscriberClass);while (findState.clazz != null) {// 通过纯反射去获取被 @Subscribe 所修饰的方法findUsingReflectionInSingleClass(findState);// 将当前 class 的父类 class 赋值给 findState.clazz findState.moveToSuperclass();}// 重置 FindState 便于下一次回收利用return getMethodsAndRelease(findState);
} 
初始化 FindState 对象后,会进入一个 while 循环中,不停地去反射获取当前类和其父类(注意,在 Java 中,如果当前类实现了一个接口,即使该接口的方法被 @Subscribe 所修饰,当前类中的方法也是不包含该注解属性的,所以如果在接口中对某个方法使用了 @Subscribe 修饰然后让类去实现这个接口是没有任何作用的)的订阅方法并添入列表中,最终返回这个列表并重置 FindState 对象利于下一次重复使用。```这里ignoreGeneratedIndex 默认为false,所以会执行findUsingInfo()方法```java
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {// 注释1处FindState findState = prepareFindState();findState.initForSubscriber(subscriberClass);while (findState.clazz != null) {// 注释2处findState.subscriberInfo = getSubscriberInfo(findState);if (findState.subscriberInfo != null) {SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();for (SubscriberMethod subscriberMethod: array) {if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {findState.subscriberMethods.add(subscriberMethod);}}} else {// 注释3处findUsingReflectionInSingleClass(findState);}findState.moveToSuperclass();}// 重置 FindState 便于下一次回收利用return getMethodsAndRelease(findState);
}

注释1处: SubscriberMethodFinder中的prepareFindState()方法:

//会先从 FIND_STATE_POOL 即 FindState 池中取出可用的 FindState(这里的POOL_SIZE为4),
//如果没有的话,则通过代码直接新建 一个新的 FindState 对象。
//由于 FindState 在注册流程中使用频繁且创建耗费资源,故创建 FindState 池复用 FindState 对象
private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];
private FindState prepareFindState() {synchronized(FIND_STATE_POOL) {for (int i = 0; i < POOL_SIZE; i++) {FindState state = FIND_STATE_POOL[i];if (state != null) {FIND_STATE_POOL[i] = null;return state;}}}return new FindState();
}

分析下FindState这个类:

static class FindState {....void initForSubscriber(Class<?> subscriberClass) {this.subscriberClass = clazz = subscriberClass;skipSuperClasses = false;subscriberInfo = null;}...
}

它是 SubscriberMethodFinder 的内部类,这个方法主要做一个初始化、回收对象等工作。

我们在回到SubscriberMethodFinder注释2处:getSubscriberInfo():

private SubscriberInfo getSubscriberInfo(FindState findState) {if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();if (findState.clazz == superclassInfo.getSubscriberClass()) {return superclassInfo;}}if (subscriberInfoIndexes != null) {for (SubscriberInfoIndex index: subscriberInfoIndexes) {SubscriberInfo info = index.getSubscriberInfo(findState.clazz);if (info != null) {return info;}}}return null;
}

这里由于初始化的时候,findState.subscriberInfo和subscriberInfoIndexes为空,所以这里直接返回null
接着我们查看注释3处的findUsingReflectionInSingleClass()方法:

private void findUsingReflectionInSingleClass(FindState findState) {Method[] methods;try {// 返回当前类自身方法和显式重载的父类方法methods = findState.clazz.getDeclaredMethods();} catch (Throwable th) {methods = findState.clazz.getMethods();findState.skipSuperClasses = true;}for (Method method: methods) {int modifiers = method.getModifiers();if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {Class<?> [] parameterTypes = method.getParameterTypes();if (parameterTypes.length == 1) {Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);if (subscribeAnnotation != null) {// 重点Class<?> eventType = parameterTypes[0];if (findState.checkAdd(method, eventType)) {ThreadMode threadMode = subscribeAnnotation.threadMode();findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode, subscribeAnnotation.priority(),  subscribeAnnotation.sticky()));}}} else if (strictMethodVerification &&     method.isAnnotationPresent(Subscribe.class)) {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)) {String methodName = method.getDeclaringClass().getName() + "." + method.getName();throw new EventBusException(methodName + " is a illegal @Subscribe method: must be public, non-static, and non-abstract");}}
}

这个方法的逻辑是:
通过反射的方式获取订阅者类中的所有声明方法,然后在这些方法里面寻找以@Subscribe作为注解的方法进行处理,先经过一轮检查,看看findState.subscriberMethods是否存在,如果有的话,将方法名,threadMode,优先级,是否为sticky方法封装为SubscriberMethod对象,添加到subscriberMethods列表中。
而实际上是需要过滤一遍的,讲解 checkAdd() 源码前,请思考以下几个问题:
对于同一个 Event,当前类对该对象使用了多个方法进行了多次订阅,那么如果该 Event 被发射的时候,当前类会如何调用这些方法?
对于同一个 Event,父类对该对象进行了一次订阅,子类重写该订阅方法,那么如果该 Event 被发射的时候,父类子类当中会如何处理这些方法?
解决这些方法就需要去看看 checkAdd() 的底层实现了:

boolean checkAdd(Method method, Class<?> eventType) {Object existing = anyMethodByEventType.put(eventType, method);if (existing == null) {return true;} else {return checkAddWithMethodSignature(method, eventType);}
}

可以看到 anyMethodByEventType 使用了 Event 的 Class 作为键,这像是意味着一个类对于同一个 Event 只能订阅一次,事实上是不是这样,还得继续看看 checkAddWithMethodSignature(),其源码简化如下:

private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {methodKeyBuilder.setLength(0);methodKeyBuilder.append(method.getName());methodKeyBuilder.append('>').append(eventType.getName());String methodKey = methodKeyBuilder.toString();Class<?> methodClass = method.getDeclaringClass();Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {return true;} else {subscriberClassByMethodKey.put(methodKey, methodClassOld);return false;}
}

可以看到 subscriberClassByMethodKey 使用方法名 + ‘>’ + 事件类型作为键,这意味着对于同一个类来说,subscriberClassByMethodKey 肯定不会键重复(毕竟一个类中不能够方法名相同且方法参数、个数都相同),因此它最终会返回 true。这意味着一个类如果使用了多个方法对同一个 Event 对象进行注册,那么当该 Event 对象被发射出来的时候,所有的方法都将会得到回调。
但是当父类执行上述操作的时候,如果子类有「显示」实现父类的订阅方法,那么此时 subscriberClassByMethodKey.put(methodKey, methodClass) 返回值不会为空,且为子类的 Class,此时 if 上分支将会判断子类 Class 是否 isAssignableFrom 父类 Class,这肯定是会为 false 的,这将会走入 if 下分支并返回 false。这意味着当子类「显示」实现父类的订阅方法的时候,如果此时发射指定 Event 的话,父类的订阅方法将不会执行,而仅会执行子类的订阅方法。

返回subscriberMethods之后,register方法的最后会调用subscribe方法:

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {//获取订阅的事件类型 Class<?> eventType = subscriberMethod.eventType;Subscription newSubscription = new Subscription(subscriber, subscriberMethod);//获取订阅该事件的订阅者集合 在subscriptionsByEventType去查找一个CopyOnWriteArrayList ,//如果没有则创建一个新的CopyOnWriteArrayListCopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);//把通过register()订阅的订阅者包装成Subscription 对象 Subscription newSubscription //= new Subscription(subscrib er, subscriberMethod); //订阅者集合为空,创建新的集合,并把newSubscription 加入if (subscriptions == null) {subscriptions = new CopyOnWriteArrayList <> ();subscriptionsByEventType.put(eventType, subscriptions);} else {if (subscriptions.contains(newSubscription)) {//集合中已经有该订阅者,抛出异常。不能重复订阅 throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType);}}int size = subscriptions.size();//添加 newSubscription对象,它是一个 Subscription 类,里面包含着 subscriber 和 subscriberMethod 等信息,//并且这里有一个优先级的判断,说明它是按照优先级添加的。优先级越高,会插到在当前 List 靠前面的位置for (int i = 0; i <= size; i++) {if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {// 根据 priority 大小放入 List 中subscriptions.add(i, newSubscription);break;}}//对typesBySubscriber 进行添加,这主要是在EventBus的isRegister()方法中去使用的,目的是用来判断这个 Subscriber对象 是否已被注册过List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);if (subscribedEvents == null) {subscribedEvents = new ArrayList<>();typesBySubscriber.put(subscriber, subscribedEvents);}subscribedEvents.add(eventType);//会判断是否是 sticky事件。如果是sticky事件的话,会调用 checkPostStickyEventToSubscription() 方法if (subscriberMethod.sticky) {//响应订阅事件的父类事件 if (eventInheritance) {Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();//循环获得每个stickyEvent事件 for (Map.Entry<Class<?>, Object> entry : entries) {Class<?> candidateEventType = entry.getKey();//是该类的父类 if (eventType.isAssignableFrom(candidateEventType)) {//该事件类型最新的事件发送给当前订阅者。Object stickyEvent = entry.getValue();checkPostStickyEventToSubscription(newSubscription, stickyEvent);}}} else {Object stickyEvent = stickyEvents.get(eventType);checkPostStickyEventToSubscription(newSubscription, stickyEvent);}}
}

我们来看下checkPostStickyEventToSubscription()方法:

private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {if (stickyEvent != null) {postToSubscription(newSubscription, stickyEvent, isMainThread());}
}

可以看到最终是调用了postToSubscription()这个方法来进行粘性事件的发送,对于粘性事件的处理,我们最后再分析,接下来我们看看事件是如何post的。

2、发布者:EventBus.getDefault().post(new Event());

先来看下post()方法:

public void post(Object event) {//PostingThreadState postingState = currentPostingThreadState.get();List <Object> 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 是一个 ThreadLocal 类,通过它获取到 PostingThreadState 对象,再根据该对象获取到 event 链表(有没有联想到 Android 中的消息机制?),并将传入的 event 塞入该链表。为了控制 Event 出队列不会被调用多次,PostingThreadState 对象有一个 isPosting 来标记当前链表是否已经开始进行回调操作,通过源码可以看到,每次分发完一个 Event 事件,该事件也会被从链表中 remove 出去。可以看下currentPostingThreadState的源码如下:

private final ThreadLocal <PostingThreadState> currentPostingThreadState = new ThreadLocal <PostingThreadState> () {
@Override
protected PostingThreadState initialValue() {return new PostingThreadState();
}
};final static class PostingThreadState {final List <Object> eventQueue = new ArrayList<>();boolean isPosting;boolean isMainThread;Subscription subscription;Object event;boolean canceled;
}

下一步进入postSingleEvent()方法

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {//分发事件的类型Class<?> eventClass = event.getClass();boolean subscriptionFound = false;//默认为true,如果设为 true 的话,它会在发射事件的时候判断是否需要发射父类事件,设为 false,能够提高一些性能。if (eventInheritance) {//它的作用就是取出 Event 及其父类和接口的 class 列表,当然重复取的话会影响性能,//所以它也做了一个 eventTypesCache 的缓存,这样就不用重复调用 getSuperclass() 方法。List<Class<?>> 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) {...}
}

然后我们在进入postSingleEventForEventType()方法:

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class <?> eventClass) {CopyOnWriteArrayList <Subscription> subscriptions;synchronized(this) {// 获取订阅事件类类型对应的订阅者信息集合.(register函数时构造的集 合) subscriptions = subscriptionsByEventType.get(eventClass);}if (subscriptions != null && !subscriptions.isEmpty()) {for (Subscription subscription: subscriptions) {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;
}

这里直接根据 Event 类型从 subscriptionsByEventType 中取出对应的 subscriptions对象,最后调用了 postToSubscription() 方法。

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 {invokeSubscriber(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("Unknow thread mode: " + subscription.subscriberMethod.threadMode);}
}

其实可以发现只用到了两种方法,一种是 invokeSubscriber 意味着立即调用该方法,另一种是 xxxPoster.enqueue() 意味着需要使用其他线程来执行该方法。
以下是threadMode 哪几种应避免耗时操作,耗时时阻塞的是哪条线程:

  • POSTING:接收事件方法应执行在发射事件方法所在的线程(由于发射事件方法线程可能是主线程,这意味着接收方法不能执行耗时操作,否则会阻塞主线程)
  • MAIN:在 Android 中则接收事件方法应执行在主线程,否则(在 Java 项目中)等同于 POSTING。如果发射事件方法已位于主线程,那么接收事件方法会被「立即」调用(这意味着接收事件方法不能执行耗时操作,否则会阻塞主线程;同时,由于是「立即」调用,所以发射事件方法此时是会被接收事件方法所阻塞的),否则等同于 MAIN_ORDERED
  • MAIN_ORDERED:在 Android 中则接收事件方法会被扔进 MessageQueue 中等待执行(这意味着发射事件方法是不会被阻塞的),否则(在 Java 项目中)等同于 POSTING。
  • BACKGROUND:
    • 在 Android 中
      • 发射事件方法在主线程中执行,则接收事件方法应执行在子线程执行,但该子线程是 EventBus 维护的单一子线程,所以为了避免影响到其他接收事件方法的执行,该方法不应太耗时避免该子线程阻塞。
      • 发射事件方法在子线程中执行,则接收事件方法应执行在发射事件方法所在的线程。
    • 在 Java 项目中,接收事件方法会始终执行在 EventBus 维护的单一子线程中。
  • ASYNC:接收方法应执行在不同于发射事件方法所在的另一个线程。常用于耗时操作,例如网络访问。当然,尽量避免在同一个时间大量触发此类型方法,尽管 EventBus 为此专门创建了线程池来管理回收利用这些线程。

3、解除订阅:EventBus.getDefault().unregister(this);

  public synchronized void unregister(Object subscriber) { // 获取该订阅者所有的订阅事件类类型集合. List<Class<?>> subscribedTypes = typesBySubscriber.get(subsc riber); if (subscribedTypes != null) { for (Class<?> eventType : subscribedTypes) { //subscriptionsByEventType 移除了该 subscriber 的所有订阅信息unsubscribeByEventType(subscriber, eventType); }// 从typesBySubscriber删除该<订阅者对象,订阅事件类类型集合> typesBySubscriber.remove(subscriber); } else { Log.e("EventBus", "Subscriber to unregister was not regi stered before: "+ subscriber.getClass()); } }
  private void unsubscribeByEventType(Object subscriber, Class<?> eventType) { // 获取订阅事件对应的订阅者信息集合. List<Subscription> 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 --; } } } }

4、发布黏性瞬间:EventBus.getDefault.postSticky(new CollectEvent())

普通事件是先注册,然后发送事件才能收到;而粘性事件,在发送事件之后再订阅该事件也能收到。此外,粘性事件会保存在内存中,每次进入都会去内存中查找获取最新的粘性事件,除非你手动解除注册

public void postSticky(Object event) {synchronized (stickyEvents) {// 先将该事件放入 stickyEvents 中stickyEvents.put(event.getClass(), event);}post(event);
}

可以看到第一步是将该事件放入 stickyEvents 中,第二步则是正常 post()。为避免多线程操作 postSticky(Object) 和 removeStickyEvent(Class<?>) 引发的冲突,所以对 stickyEvents 对象添加了 synchronized 关键字,
前面我们在分析register()方法的最后部分时,其中有关粘性事件的源码如下:

if (subscriberMethod.sticky) {Object stickyEvent = stickyEvents.get(eventType);if (stickyEvent != null) {postToSubscription(newSubscription, stickyEvent, isMainThread());}
}

可以看到,在这里会判断当前事件是否是 sticky 事件,如果是,则从 stickyEvents 中拿出该事件并执行 postToSubscription() 方法。

好了EventBus源码到此结束了。

总结

EventBus 源码都说简单我可没看出简单啊,当中的很多设计技巧是非常值得学习的,例如前文提到的复用池,以及遍布 EventBus 源码各处的 synchronized 关键字。笔者也是第一次写源码的分析,也是借鉴网上的大佬们的文章。

参考链接:
Android主流三方库源码分析(九、深入理解EventBus源码)
聊一聊 EventBus 源码和设计之禅
EventBus 3.1.1 源码解析

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 原定于4月下旬举行的北京国际电影节宣布延期

    原标题:原定于4月下旬举行的北京国际电影节宣布延期2020年北京国际电影节宣布延期。 据北京国际电影节官方微信公号消息,为配合好现阶段对新冠肺炎的防疫工作大局,本着为电影节嘉宾、影迷、媒体、合作方及公众安全健康考虑,经征求电影节指导单位、主办单位及各界专家意见,…...

    2024/5/4 21:29:28
  2. 设计模式遵循的六大原则

    1.单一职责原则(SRP) 1.就一个类而言,应该只有一个引起他变化的原因。 2.一个类应该是一组高度相关的方法、数据的封装 3.也就是高内聚。 2.开放关闭原则(OCP) 对修改关闭,对扩展开放 3.里氏替换原则(LSP) 1.继承 2.所有引用父类的地方,必须能透明的使用其子类对象,只…...

    2024/4/28 20:56:19
  3. 亚洲第一长船坞12天出坞

    原标题:亚洲第一长船坞12天出坞亚洲第一长船坞12天出坞 摄记天下(记者 常魁星 通讯员 王学森)3月7日,随着一艘浮式生产储油船(FPSO)出坞、一艘21万吨纽卡斯尔型散货船艏艉两个巨型分段同时起浮,中交三航局承建的大型邮轮船厂适应性改造重点工程——2号船坞改造项目主体结…...

    2024/4/28 20:56:09
  4. 小和尚明白了,亳州万达什么都有。

    原标题:小和尚明白了,亳州万达什么都有。 小和尚明白了,亳州万达什么都有。 一和尚要云游亳州万达。 师傅问:“什么时候动身?” “下个星期。路途远,我托人打了几双草鞋,取货后就动身。” 师父沉吟一会儿,说:“不如这样,我来请信众捐赠。" 师父不知道告诉…...

    2024/4/28 20:56:06
  5. UGUI之修改Text字间距

    using UnityEngine; using System.Collections; using UnityEngine.UI; using System; using System.Collections.Generic;public class Line {private int _startVertexIndex = 0;/// <summary>/// 起点索引/// </summary>public int StartVertexIndex{get{return…...

    2024/4/28 20:56:02
  6. 香嘴儿 | 狗狗口臭,可能是因为这些原因

    原标题:香嘴儿 | 狗狗口臭,可能是因为这些原因如果要问,养狗最大的困扰是什么,大概90%的人,都会说狗口臭,狗狗口臭的问题经常会发生,于是越来越多的人,我要发亲近自己的狗狗,进而产生厌恶,甚至是弃养。那么,狗狗口臭是怎么回事呢,可能事以下几点原因。 1、与你喂养…...

    2024/4/28 20:55:58
  7. POI对表格的数据读取和写入

    1.新建一个maven项目 在pom.xml文件中引入相关依赖 <dependencies><!-- xls 操作2003版本Excel --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.9</version></dependency…...

    2024/4/28 20:55:54
  8. 照片:LOL玩家Cos安妮 网友评论:不好看!

    原标题:照片:LOL玩家Cos安妮 网友评论:不好看!玩家在微博上发布的安妮cos照片,服装表情非常到位,相似度很高,最后一张与游戏原画的PS更是神似。 责任编辑:...

    2024/5/4 20:59:21
  9. PaddlePaddle 核心架构深入解读

    个人博客导航页(点击右侧链接即可打开个人博客):大牛带你入门技术栈 PaddlePaddle(中文名:飞桨,PArallel Distributed Deep LEarning 并行分布式深度学习)是一个深度学习平台,具有易用、高效、灵活和可伸缩等特点,它是中国第一个开源深度学习开发框架。飞桨框架的核心…...

    2024/5/4 15:46:37
  10. 细数南京城北板块价值被严重低估的公寓楼盘

    原标题:细数南京城北板块价值被严重低估的公寓楼盘2016年7月南京房价环比涨幅2.39%,虽然比起6月3.82%的涨幅有所收敛,但是不可否认的是南京房价已经实现了17连涨。南京住宅市场的豪宅化趋势越来越明显,因此许多人将目光投向了置业门槛较低的公寓市场,而城北因为距离主城核…...

    2024/4/28 20:55:42
  11. 为什么java源文件有且只能有一个public类

    一个.java文件中只能有一个public修饰的类,编译器就会给出错误信息 java将public类作为每个编译单元(java文件)的数据接口,只能有一个, 虽然不是很常用,但编译单元内完全不带public类也是可能的 如图此时程序编译通过,在相应路径下产生了三个.class文件。直接点击运行,…...

    2024/4/28 7:26:54
  12. 高手笔记:周五复盘(市场情绪不容乐观)

    原标题:高手笔记:周五复盘(市场情绪不容乐观)整个市场不绝于耳的就是对641的种种声讨,其实这是一种极端情绪化的集中宣泄,但这就是目前市场的监管现状,短期不可能又太大的变化,作为市场的参与者,如果不能很好的控制自身情绪任其蔓延,到最后结果都不会好。这是吃了一天…...

    2024/4/28 10:38:11
  13. [热点聚焦]首届中国木材指数建设高峰论坛在莆田标准红木交易中心举行

    原标题:[热点聚焦]首届中国木材指数建设高峰论坛在莆田标准红木交易中心举行上周,首届中国(莆田)木材指数建设高峰论坛在莆田标准红木交易中心举行。市政府副市长蒋志雄、省林业厅处长邓荣俤、市商务局局长梁国镇、秀屿区区长郑加清、仙游县政协主席何锦驰、木材管委会主任…...

    2024/4/27 21:22:10
  14. 在寻爱吧竟然约到真爱了!

    原标题:在寻爱吧竟然约到真爱了!我今年28,还没交过女朋友。。这几天一位朋友推荐我一个好玩的公众平台,说是可以认识许多美女,聊的好的话,约出来,没准就成女朋友了。我当时觉得我朋友是在吹牛X,因为我之前一直使用各种相亲平台,大部分女的都是贼丑,要么就是贼老那种(…...

    2024/4/28 19:17:28
  15. 财税体制改革进入攻坚阶段 央地财政关系改革或将提速

    原标题:财税体制改革进入攻坚阶段 央地财政关系改革或将提速来源:上海证券报 财税体制改革尤其是央地财政关系改革,最近再次成为热点话题之一。 作为财税体制改革三大任务之首,央地财政关系改革的重要性不言而喻。这项改革被认为是最难啃的“硬骨头”,一直进展缓慢。按照…...

    2024/4/28 9:18:31
  16. 2018,你准备储存哪些有意义的事情?

    原标题:2018,你准备储存哪些有意义的事情?如果快乐、生活、工作都像存折一样, 2017年你准备储存哪些有意义的事情? 存储快乐 爱时,一见面就“亲嘴” 结婚后,一见面就“斗嘴” 云棒存储属于我们的快乐时光, 是记载幸福和甜蜜的专属。 存储生活 再好的东西都有失…...

    2024/4/28 20:55:26
  17. 90 现代简约混搭地中海,满满的温馨

    原标题:90 现代简约混搭地中海,满满的温馨▲ 进门左手边是一条比较长的走廊通往厨房 ▲ 利用走廊空间除了鞋柜之外,做了洗手台,放置了洗衣机 ▲ 自砌的洗手台,以蓝色马赛克做背景 ▲ 这个区域还是有比较明显地中海风格调调的 ▲ 进门向右是餐厅、客厅区域,地板和瓷砖在这…...

    2024/4/28 20:55:22
  18. 中国,有哪些适合夏季旅行的地方

    原标题:中国,有哪些适合夏季旅行的地方立夏过后,夏天就正式来了。天气越来越炎热,这些适合夏季旅行的地方,你知道几个? 1九寨沟 九寨沟,因沟内有九个藏族寨子而得名,“九寨归来不看水”,是对九寨沟景色真实的诠释。 泉、瀑、河、滩108个海子,构成一个个五彩斑斓的瑶…...

    2024/4/28 2:01:30
  19. 张少博:世界级小提琴演奏家为家乡电影节站台

    原标题:张少博:世界级小提琴演奏家为家乡电影节站台6月22日下午,第十四届中国长春电影节“新时代 新摇篮 新力量——中国长春电影节之约”推介会在上海龙之梦举行。世界级小提琴家张少博(吉林籍)不远万里从美国飞回上海,为家乡电影节站台助力。这次主办方能够邀请到张少博…...

    2024/4/28 7:46:42
  20. 马云;四大银行你直接放招过来!不可能移民

    原标题:马云;四大银行你直接放招过来!不可能移民马云和银行一直都有各种较量,各种不服谁也看不惯谁。以前马云刚创业不久的时候找银行借钱,银行不给,那个时候就结下了矛盾。 马云说自己要改变银行:现如今也成功的改变了银行的传统模式!但是问题来了,银行不放过马云了…...

    2024/4/28 20:55:10

最新文章

  1. Iterable和Iterator,你学会了吗?

    在 Java 编程中&#xff0c;Iterable 和 Iterator 是用于实现集合类&#xff08;如列表、集合、映射等&#xff09;迭代访问的重要接口。 它们提供了一种统一的方式来遍历集合中的元素&#xff0c;并在不同的集合类型之间提供了一致的迭代访问方式。 本文将深入探讨 Iterable…...

    2024/5/5 1:12:53
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 蓝桥杯第十五届抱佛脚(十)贪心算法

    蓝桥杯第十五届抱佛脚&#xff08;十&#xff09;贪心算法 贪心算法基本概念 贪心算法是一种在算法设计中常用的方法&#xff0c;它在每一步选择中都采取在当前状态下最好或最优&#xff08;即最有利&#xff09;的选择&#xff0c;从而希望导致结果是最好或最优的算法。 贪…...

    2024/5/2 2:39:45
  4. linuxday05

    1、makedile原理&#xff08;增量编译生成代码&#xff09; # &#xff08;注释符&#xff09; 目标------依赖 目标不存在//目标比依赖旧才会执行命令&#xff1b; makefile的实现 1、命名要求&#xff08;Makefile/makefile&#xff09; 2、规则的集合 目标文件&#…...

    2024/5/4 6:30:26
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/4 23:54:56
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/4 23:54:56
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/4 23:55:17
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/4 23:55:16
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/4 18:20:48
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/4 23:55:17
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/4 23:55:06
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/4 23:55:06
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/4 2:59:34
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/4 23:55:16
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/4 23:55:01
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57