[关闭]
@TryLoveCatch 2022-06-07T15:20:19.000000Z 字数 4643 阅读 547

Android知识体系之第三方框架EventBus

Android知识体系


使用

定义事件->注册订阅->发布事件 ->处理事件

1、定义事件,其实就是一个普通的实体类

  1. class EventTest {
  2. private String url,name;
  3. public String getName() {
  4. return name;
  5. }
  6. public void setName(String name) {
  7. this.name = name;
  8. }
  9. public String getUrl() {
  10. return url;
  11. }
  12. public void setUrl(String url) {
  13. this.url = url;
  14. }
  15. }

2、在Activity的onCreate和onDestroy里面分贝注册监听和反注册监听。

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. ...
  4. ...
  5. //注册监听
  6. EventBus.getDefault().register(this);
  7. }
  1. @Override
  2. protected void onDestroy() {
  3. super.onDestroy();
  4. //反注册
  5. EventBus.getDefault().unregister(this);
  6. }

3、在另一个Activity或者数据处理层里面 发布事件。

  1. EventTest event = new EventTest();
  2. event.setName("111");
  3. event.setUrl("www.baidu.com");
  4. EventBus.getDefault().post(event);

4、在之前注册的Activity里面@Subscribe注解标记的方法,会被调用。

  1. @Subscribe(threadMode = ThreadMode.POSTING, priority = 0, sticky = true)
  2. public void onEvent(EventTest event) {
  3. String name = event.getName();
  4. String url = event.getUrl();
  5. Log.e("点击",name+":"+url);
  6. };

原理

核心架构

注册事件

发送事件

  1. private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
  2. @Override
  3. protected PostingThreadState initialValue() {
  4. return new PostingThreadState();
  5. }
  6. };
  7. /**
  8. * 线程的发送状态
  9. */
  10. final static class PostingThreadState {
  11. final List<Object> eventQueue = new ArrayList<Object>(); //当前线程的事件队列
  12. boolean isPosting;
  13. boolean isMainThread;
  14. Subscription subscription;
  15. Object event;
  16. boolean canceled;
  17. }

四种threadMode

  1. /**
  2. * 根据 threadMode 发送事件给该订阅者
  3. * @param subscription
  4. * @param event
  5. * @param isMainThread
  6. */
  7. private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
  8. switch (subscription.subscriberMethod.threadMode) {
  9. case POSTING: //直接在当前线程调用
  10. invokeSubscriber(subscription, event);
  11. break;
  12. case MAIN: //订阅方法要在主线程执行
  13. if (isMainThread) { //当前就在主线程,直接调用
  14. invokeSubscriber(subscription, event);
  15. } else { //入队,handler 发送消息到主线程,在主线程中反射调用
  16. mainThreadPoster.enqueue(subscription, event);
  17. }
  18. break;
  19. case BACKGROUND:
  20. if (isMainThread) { //放到子线程线程池中执行
  21. backgroundPoster.enqueue(subscription, event);
  22. } else {
  23. invokeSubscriber(subscription, event);
  24. }
  25. break;
  26. case ASYNC: //直接在子线程中执行
  27. asyncPoster.enqueue(subscription, event);
  28. break;
  29. default:
  30. throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
  31. }
  32. }

反注册事件

  1. /**
  2. * 解除注册很简单,就从两个属性中移除当前类
  3. * @param subscriber
  4. */
  5. public synchronized void unregister(Object subscriber) {
  6. List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
  7. if (subscribedTypes != null) {
  8. //找到这个类中所有的订阅方法,挨个取消注册
  9. for (Class<?> eventType : subscribedTypes) {
  10. unsubscribeByEventType(subscriber, eventType);
  11. }
  12. //移除这个订阅记录
  13. typesBySubscriber.remove(subscriber);
  14. } else {
  15. Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
  16. }
  17. }
  18. private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
  19. //获取订阅这个事件的订阅者列表
  20. List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
  21. if (subscriptions != null) {
  22. int size = subscriptions.size(); //只调用一次 subscriptions.size(),比在循环里每次都调用 subscriptions.size() 好
  23. for (int i = 0; i < size; i++) {
  24. Subscription subscription = subscriptions.get(i);
  25. if (subscription.subscriber == subscriber) { //将当前订阅者从订阅这个事件的订阅者列表中删除
  26. subscription.active = false;
  27. subscriptions.remove(i);
  28. i--;
  29. size--;
  30. }
  31. }
  32. }
  33. }

索引加速

在编译时apt插件通过EventBusAnnotationProcessor分析注解,并利用注解标识的相关类的信息去生成相关的类。

小结

参考

Android 主流开源库源码分析(一)- EventBus 源码详解
Android 主流开源库源码分析(二)- EventBus 自己实现一个

Android面试之EventBus原理分析
Android事件总线(二)EventBus3.0源码解析
老司机教你 “飙” EventBus 3
Android 框架学习2:源码分析 EventBus 3.0 如何实现事件总线

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注