EventBus记录01

目录

1.项目引用

2.基本用法

3.源码分析

3.1.注册

3.2 事件的分发 


这是对使用EventBus的记录,如果有错误的地方请多指教,不喜勿喷。

1.项目引用

implementation("org.greenrobot:eventbus:3.3.1")

2.基本用法

class EventBusActivity : AppCompatActivity() {

    data class MessageEvent(val msg: String)

    /**
     * 方法名称可以任意命名
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onMessageEvent(msg: MessageEvent) {
        Log.d("all_log", "EventBus 订阅事件回调处理。。。")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        ..........
        //注册订阅
        EventBus.getDefault().register(this)
    }

    override fun onDestroy() {
       ..........
        //反注册订阅
        EventBus.getDefault().unregister(this)
    }
}

//发送事件
EventBus.getDefault().post(MessageEvent("消息事件"))

3.源码分析

private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
//订阅方法参数类型<eventClass,List<eventClass及父接口类型>>
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
//key:订阅方法的参数类型,value:Subscription(订阅对象,订阅方法)
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//订阅者,跟订阅参数类型集合 typesBySubscriber<订阅对象,list<订阅参数类型>>
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;

private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
        @Override
        protected PostingThreadState initialValue() {
            return new PostingThreadState();
        }
    };

3.1.注册

  EventBus.getDefault().register(this)

通过上面的注册订阅我们来看下EventBus.getDefault()做了什么。

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

通过上面的源码可以看出这就是我们常说的 单例模式 来创建EventBus对象,保证创建出来的对象都是同一个。下面看下创建EventBus的具体过程

//建造模式,配置EventBus的信息
public class EventBusBuilder {

    //默认切换到子线程用到的线程池是无限制的,如果大量发送事件可能会OOM
    private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = 
Executors.newCachedThreadPool();

    //>>>>>>> 日志相关
    boolean logSubscriberExceptions = true;
    boolean logNoSubscriberMessages = true;
    boolean sendSubscriberExceptionEvent = true;
    boolean sendNoSubscriberEvent = true;
    boolean throwSubscriberException;
    //子类发送事件,是否需要发送父类事件
    boolean eventInheritance = true;
    boolean ignoreGeneratedIndex;
    boolean strictMethodVerification;
    ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
    List<Class<?>> skipMethodVerificationForClasses;
    List<SubscriberInfoIndex> subscriberInfoIndexes;
    Logger logger;
    MainThreadSupport mainThreadSupport;
}

EventBus(EventBusBuilder builder) {
    //日志输出
	logger = builder.getLogger();
	subscriptionsByEventType = new HashMap<>();
	typesBySubscriber = new HashMap<>();
	stickyEvents = new ConcurrentHashMap<>();
	mainThreadSupport = builder.getMainThreadSupport();
    //主线程处理
	mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
    //后台线程处理
	backgroundPoster = new BackgroundPoster(this);
    //异步线程处理
	asyncPoster = new AsyncPoster(this);

	indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
    
    //订阅方法查找类
	subscriberMethodFinder = new SubscriberMethodFinder(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;
}

有了EventBus对象接下来就要注册订阅了

public void register(Object subscriber) {
	
	//订阅对象 如Activity...
	Class<?> subscriberClass = subscriber.getClass();
	
	//SubscriberMethod 封装了订阅方法相关信息 如方法,线程类型...
	List<SubscriberMethod> subscriberMethods = 
		//查找订阅的方法
		subscriberMethodFinder.findSubscriberMethods(subscriberClass);
	synchronized (this) {
		for (SubscriberMethod subscriberMethod : subscriberMethods) {
            //查找到相关订阅方法后 开始订阅
			subscribe(subscriber, subscriberMethod);
		}
	}
}

public class SubscriberMethod {
    final Method method; //订阅方法
    final ThreadMode threadMode;//线程类型
    final Class<?> eventType;//事件类型 --- 订阅的方法参数类型
    final int priority;//优先级
    final boolean sticky;//是否是粘性订阅
	.....
}

现在我们看下 subscriberMethodFinder.findSubscriberMethods(subscriberClass) 具体做了什么。

class SubscriberMethodFinder {
    
/*
 * 缓存订阅对象的方向集合
 * key:订阅对应如Activity ,value:是订阅方法集合
*/
 private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = 
    new ConcurrentHashMap<>();


List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        //查找到缓存直接返回
        if (subscriberMethods != null) {
            return subscriberMethods;
        }

        if (ignoreGeneratedIndex) {
            //默认是false  不执行这里 通过运行反射获取
            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;
        }
    }

}

现在看下subscriberMethods = findUsingReflection(subscriberClass);是如何查找订阅方法的

private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
	FindState findState = prepareFindState();
	findState.initForSubscriber(subscriberClass);
	while (findState.clazz != null) {
		//通过反射获取订阅方法
		findUsingReflectionInSingleClass(findState);
		//findState.clazz 定位到位父class
		findState.moveToSuperclass();
	}
	 //释放FindState到缓存中 返回订阅方法集合
	return getMethodsAndRelease(findState);
}

现在看下 subscriberMethods = findUsingInfo(subscriberClass);是如何查找订阅方法的,

private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {

	//FindState 有复用默认缓存4个
	FindState findState = prepareFindState();
	findState.initForSubscriber(subscriberClass);
	while (findState.clazz != null) {
       /*
        * subscriberInfo从SubscriberInfoIndex获取 如果获取不到
        * 也是通过反射来获取订阅的方法信息
        */
		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 {
            //反射获取订阅方法
			findUsingReflectionInSingleClass(findState);
		}
        //查找父类订阅方法
		findState.moveToSuperclass();
	}
    //释放FindState到缓存中 返回订阅方法集合
	return getMethodsAndRelease(findState);
}

private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
	List<SubscriberMethod> 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;
				break;
			}
		}
	}
	return subscriberMethods;
}

static class FindState {
	final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
	final Map<Class, Object> anyMethodByEventType = new HashMap<>();
	final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
	final StringBuilder methodKeyBuilder = new StringBuilder(128);
	
	//订阅类如Activity
	Class<?> subscriberClass;
	Class<?> clazz;
	boolean skipSuperClasses;
	SubscriberInfo subscriberInfo;
	//初始化下
	void initForSubscriber(Class<?> subscriberClass) {
		this.subscriberClass = clazz = subscriberClass;
		skipSuperClasses = false;
		subscriberInfo = null;
	}
	.....
}

现在看下反射的获取方式 findUsingReflectionInSingleClass(findState)

private void findUsingReflectionInSingleClass(FindState findState) {
	Method[] methods;
	try {
		//通过反射获取方法
		methods = findState.clazz.getDeclaredMethods();
	} catch (Throwable th) {
		// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
		try {
			methods = findState.clazz.getMethods();
		} catch (LinkageError error) { // super class of NoClassDefFoundError to be a bit more broad...
			String msg = "Could not inspect methods of " + findState.clazz.getName();
			if (ignoreGeneratedIndex) {
				msg += ". Please consider using EventBus annotation processor to avoid reflection.";
			} else {
				msg += ". Please make this class visible to EventBus annotation processor to avoid reflection.";
			}
			throw new EventBusException(msg, error);
		}
		//是否跳过父类
		findState.skipSuperClasses = true;
	}
	for (Method method : methods) {
		//方法修饰符 要是public
		int modifiers = method.getModifiers();
		if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
			Class<?>[] parameterTypes = method.getParameterTypes();
			//订阅方法的参数只能一个
			if (parameterTypes.length == 1) {
				/*
				* public @interface Subscribe {
				*    线程 默认执行在 当前调用线程
				*    ThreadMode threadMode() default ThreadMode.POSTING;
				*    是否是粘性
				*    boolean sticky() default false;
				*    优先级
				*    int priority() default 0;
				* }
				* */
				//Subscribe 订阅方法注解
				Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
				if (subscribeAnnotation != null) {
					//拿到参数类型class对象
					Class<?> eventType = parameterTypes[0];
					if (findState.checkAdd(method, eventType)) {
						//获取注解值
						ThreadMode threadMode = subscribeAnnotation.threadMode();
						//创建SubscriberMethod
						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(subscriber, subscriberMethod);

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
	Class<?> eventType = subscriberMethod.eventType;
	//将订阅对象和订阅方法封装成Subscription
	Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
	//判断是否添加过,如果添加过就抛出EventBusException
	CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
	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);
		}
	}

	//根据优先级 添加Subscription
	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);
			break;
		}
	}
	
	//订阅对象 和订阅方法类行 保存在 typesBySubscriber中
	//伪代码结构:typesBySubscriber<订阅对象,list<订阅参数类型>> 
	List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
	if (subscribedEvents == null) {
		subscribedEvents = new ArrayList<>();
		typesBySubscriber.put(subscriber, subscribedEvents);
	}
	subscribedEvents.add(eventType);
	
	//如果是粘性事件 就开发分发 订阅消息
	if (subscriberMethod.sticky) {
		if (eventInheritance) {
			// 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 -> List<Class>).
			Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
			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);
		}
	}
}

总结:订阅的基本流程

3.2 事件的分发 

public void post(Object event) {

	/*
    *  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; true:标记当前正在分发事件
	*		boolean isMainThread;
	*		Subscription subscription;
	*		Object event;//消息事件 post(消息事件)
	*		boolean canceled;
	*	}
	*	currentPostingThreadState是ThreadLocal<PostingThreadState> 
	*	ThreadLocal:保存当前线程的Post 状态
	*/

	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;
		}
	}
}

ThreadLocal:可以理解为线程独有的存储区域,不与其他线程共享,Handler中也有用到

现在看下 postSingleEvent(eventQueue.remove(0), postingState);

 private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
	//订阅方法的参数类型
	Class<?> eventClass = event.getClass();
	boolean subscriptionFound = false;
	if (eventInheritance) {
		//查找eventClass 的父类及自己的接口类型
		// class MessageEvent implements Event
		// 那么查找到 MessageEvent和Event 
		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) {
		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));
		}
	}
}

接着进入 postSingleEventForEventType(...)

private boolean postSingleEventForEventType(
	Object event, //订阅方法参数对象
	PostingThreadState postingState, //当前线程的分发状态
	//订阅方法参数类型
	Class<?> eventClass) {
		CopyOnWriteArrayList<Subscription> subscriptions;
		synchronized (this) {
			//获取通过参数类型 获取订阅方法列表
			subscriptions = subscriptionsByEventType.get(eventClass);
		}
		if (subscriptions != null && !subscriptions.isEmpty()) {
			for (Subscription subscription : subscriptions) {
				postingState.event = event;
				postingState.subscription = subscription;
				boolean aborted;
				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;
}

现在到关键的一步,对消息进行分发及线程切换 

postToSubscription(subscription, event, postingState.isMainThread)
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
	switch (subscription.subscriberMethod.threadMode) {
		case POSTING:
			//默认执行线程类型,post在什么线程,就在什么线程分发
			
			invokeSubscriber(subscription, event);
			break;
		case MAIN:
			//主线程 如果在子线程,就用handler切换到主线程
			if (isMainThread) {
				invokeSubscriber(subscription, event);
			} else {
				mainThreadPoster.enqueue(subscription, event);
			}
			break;
		case MAIN_ORDERED:
			//如果主线程mainThreadPoster!=null 就post到主线程中去执行
			//否则就在post线程中去执行
			if (mainThreadPoster != null) {
				mainThreadPoster.enqueue(subscription, event);
			} else {
				// temporary: technically not correct as poster not decoupled from subscriber
				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("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值