EventBus学习笔记

如果对EventBus原理不太熟悉的童鞋可以看这个:

EventBus 原理解析

1.极其简单的订阅-发布-接收模式

public class Publisher {
    private Publisher() {
    }
    public static Publisher getDefault(){
        return PublishHoler.sPublisher;
    }
    public List subscribeByEventTypes=new ArrayList<>();
    public void register(ISubScriber subScriber){
        subscribeByEventTypes.add(subScriber);
    }
    public void unRegister(ISubScriber subScriber){
        subscribeByEventTypes.remove(subScriber);
    }
    public void post(EventType eventType){
        for(ISubScriber subScriber:subscribeByEventTypes){
            subScriber.receive(eventType);
        }
    }
    public static class PublishHoler{
        private static Publisher sPublisher=new Publisher();
    }
}
public interface ISubScriber {
   void receive(EventType eventType);
}
public class EventType {
    public String message;

    public EventType(String message) {
        this.message = message;
    }
}
public class Subscriber1 implements  ISubScriber {
    public Subscriber1() {
        Publisher.getDefault().register(this);
    }

    @Override
    public void receive(EventType eventType) {
        System.out.println(eventType.message);
    }
}

这是一个极其粗糙的订阅发送的例子,完全不能用于生产。

Q:如果有多个订阅者,每个订阅者也有多种感兴趣事件,怎么做到在发送某种事件时,只触发该事件的接收?

A:接收的方法可自行定义,唯一的参数就是发送的事件,添加指定注解(@Subscribe)方便注册时反射查找。

 @Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 2)
    public void onMessageEvent(NotifyMessage event) {
        System.out.println(event.message);
       
    }
//源码里面查找注解
 Method[] methods;
        try {
            // This is faster than getMethods, especially when subscribers are fat classes like Activities
            //todo 找本类的方法
            methods = findState.clazz.getDeclaredMethods();
        } catch (Throwable th) {
            // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
            //todo 找本类以及父类的所有公共方法
            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) {
                        //事件类型就是我们MessageEvent
                        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 (....){
            }
        }
    }

Q:使用到了什么设计模式?

A:有两处使用了享元设计模式,使用缓存的对象去处理:
第一处: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();
    }
    private List getMethodsAndRelease(FindState findState) {
        List 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;
    }
调用:
 private List findUsingInfo(Class subscriberClass) {
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);
        ......省略....
        return getMethodsAndRelease(findState);
    }

第二处:PendingPost

private final static List pendingPostPool = new ArrayList();

  Object event;
  Subscription subscription;
  PendingPost next;

   private PendingPost(Object event, Subscription subscription) {
        this.event = event;
        this.subscription = subscription;
    }

   static PendingPost obtainPendingPost(Subscription subscription, Object event) {
        synchronized (pendingPostPool) {
            int size = pendingPostPool.size();
            if (size > 0) {
                //从第一个取出来和最后一个取出来都没区别,享元模式而已
                PendingPost pendingPost = pendingPostPool.remove(size - 1);
                pendingPost.event = event;
                pendingPost.subscription = subscription;
                pendingPost.next = null;
                return pendingPost;
            }
        }
    return new PendingPost(event, subscription);
    }

static void releasePendingPost(PendingPost pendingPost) {
   pendingPost.event = null;
   pendingPost.subscription = null;
   pendingPost.next = null;
    synchronized (pendingPostPool) {
     // Don't let the pool grow indefinitely 这里写10000和写4个没区别??
            if (pendingPostPool.size() < 10000) {
                pendingPostPool.add(pendingPost);
            }
        }
    }
调用:
@Override
    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
     ..........
    }
 void invokeSubscriber(PendingPost pendingPost) {
        Object event = pendingPost.event;
        Subscription subscription = pendingPost.subscription;
        PendingPost.releasePendingPost(pendingPost);
        if (subscription.active) {
            invokeSubscriber(subscription, event);
        }
    }

Q:多个订阅者多个订阅方法怎么保证事件发送的优先级?

A: 根据注解上的优先级调整map顺序

CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(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);
                break;
            }
        }

Q:为什么发送事件时使用队列(PendingPostQueue)?

A:我觉得没必要使用,其他童鞋能解释下吗?

HandlePoster实现(public class HandlerPoster extends Handler implements Poster)

 @Override
    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!handlerActive) {
                handlerActive = true;
                //插进去立马就发送消息
                if (!sendMessage(obtainMessage())) {
                    throw new EventBusException("Could not send handler message");
                }
            }
        }
    }

BackgroundPoster实现(final class BackgroundPoster implements Runnable, Poster)

 @Override
    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        //后台线程的话,对插入做了一个同步
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!executorRunning) {
                executorRunning = true;
                eventBus.getExecutorService().execute(this);
            }
        }
    }

AsyncPoster实现(class AsyncPoster implements Runnable, Poster)

 @Override
    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        queue.enqueue(pendingPost);
        //可以多次插入多次调用
        eventBus.getExecutorService().execute(this);
    }

你可能感兴趣的:(EventBus学习笔记)