框架原理之EventBus

6 阅读2分钟
1.EventBus使用
  • 原理: (反射 + 观察者模式)
        EventBus.getDefault().register(this); //注册
        EventBus.getDefault().unregister(this); //移除
        EventBus.getDefault().post(new Object());//发送事件

/*
注册(Register):订阅者通过调用EventBus的register方法注册到EventBus中,并指定自己感兴趣的事件类型。注册时,EventBus会利用反射机制查找订阅者类中带有@Subscribe注解的方法,并将这些方法与事件类型进行关联。

发布(Post):发布者通过调用EventBus的post方法发布一个事件。EventBus会遍历所有已注册的订阅者,找到与事件类型匹配的订阅者,并调用其对应的处理方法。

处理(Handle):订阅者接收到事件后,会执行与事件类型匹配的处理方法。处理方法的执行线程可以根据@Subscribe注解中的threadMode属性进行指定,包括POSTING(发布线程)、MAIN(主线程)、BACKGROUND(后台线程)和ASYNC(异步线程)等。
*/
2.EventBus.getDefault().register(this)流程分析
public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
  
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

通过反射拿到类中所有含有@Subscribe注解的方法集合

  List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
  List<SubscriberMethod>  list=new ArrayList<SubscriberMethod>();
     Method[]  methods = subscriberClass.getDeclaredMethods(); //通过反射拿到类中所有方法集合
     for (Method method : methods) {
      //找到还有Subscribe方法的集合
         Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
        Class<?>[] parameterTypes = method.getParameterTypes();
         if (subscribeAnnotation != null) {
              Class<?> eventType = parameterTypes[0];
            /*构造订阅方法SubscriberMethod类*/
              list.add(new SubscriberMethod(method,eventType,threadMode));
         }
    }
}
  private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType= new HashMap<>();
 private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
       //构建一个Subscription订阅类,把方法和观察者进行关联
      Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        //通过订阅方法类,得到事件类型
      Class<?> eventType = subscriberMethod.eventType;
         //实例化订阅者集合
       CopyOnWriteArrayList<Subscription>   subscriptions=subscriptionsByEventType.get(eventType);
    if (subscriptions == null) {
      subscriptions=new CopyOnWriteArrayList<>();
    }
   //订阅者集合中添加一个新的订阅
    subscriptions.add(newSubscription);
 //map集合保存key=eventType ,value=subscriptions集合列表
    subscriptionsByEventType.put(eventType, subscriptions);
}
3.Event.getDefault().post(new PostBean())流程解析
    public void post(Object event) {
           for (Subscription subscription : subscriptions) {
            //根据订阅的threadMode类型,决定实在主线程还是在异步线程或者后台线程中执行invoke方法
                  switch (subscription.subscriberMethod.threadMode) {
                          case POSTING:
                                subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
                               break;
                         case MAIN:
                                subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
                           break;
           case BACKGROUND:  //后台线程
                              backgroundPoster.enqueue(subscription, event);  //启动线程池执行
                           break;
                      case ASYNC://异步线程
                               asyncPoster.enqueue(subscription, event);//启动线程池执行
                           break;
                  }
           }
    }

public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        queue.enqueue(pendingPost);
        eventBus.getExecutorService().execute(this);//启动线程池执行
    }