美文网首页
EventBus学习笔记

EventBus学习笔记

作者: doc__wei | 来源:发表于2019-07-27 16:23 被阅读0次

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

EventBus 原理解析

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

public class Publisher {
    private Publisher() {
    }
    public static Publisher getDefault(){
        return PublishHoler.sPublisher;
    }
    public List<ISubScriber> 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<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;
    }
调用:
 private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);
        ......省略....
        return getMethodsAndRelease(findState);
    }

第二处:PendingPost

private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();

  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<Subscription> 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原理解析笔记以及案例实战(结合demo)

    笔记概述 EventBus简介 EventBus方法介绍 EventBus实际运用 EventBus简介 开源项目...

  • EventBus源码详解

    EventBus笔记 一、EventBus使用 EventBus使用有四步骤: 二、Eventbus.getDef...

  • EventBus学习笔记

    该文为个人学习笔记,如有错误,烦请大佬指出~~~ 说明:1.onCreate 注册: EventBus.getDe...

  • EventBus学习笔记

    EventBus学习笔记 使用方法 (1)首先需要定义一个消息类,该类可以不继承任何基类也不需要实现任何接口。例如...

  • EventBus学习笔记

    它是一个基于观察者模式的事件发布/订阅框架,开发者可以通过极少的代码去实现多个模块之间的通信,而不需要以层层传递接...

  • EventBus学习笔记

    (官方一点的说法:EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,H...

  • EventBus学习笔记

    如果对EventBus原理不太熟悉的童鞋可以看这个: EventBus 原理解析 1.极其简单的订阅-发布-接收模...

  • 学习笔记EventBus

    深度学习一下EventBus的原理 用法 官网给的使用方法,一个类,一个带有 @Subscribe 注解的方法,在...

  • Eventbus3.0版本用到的一些知识

    # Eventbus 笔记 ## EventBus是什么eventbus是一个基于观察者模式的事件发布订阅框架,开...

  • Android 学习笔记 EventBus

    android EventBus的简单使用 https://blog.csdn.net/bzlj291200959...

网友评论

      本文标题:EventBus学习笔记

      本文链接:https://www.haomeiwen.com/subject/exuerctx.html