package com.yalantis.ucrop.rxbus2; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import io.reactivex.BackpressureStrategy; import io.reactivex.Flowable; import io.reactivex.Scheduler; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; import io.reactivex.functions.Function; import io.reactivex.functions.Predicate; import io.reactivex.schedulers.Schedulers; import io.reactivex.subjects.PublishSubject; import io.reactivex.subjects.Subject; /** * RxBus * Created by gorden on 2016/5/12. * update 2017/3/1 */ @SuppressWarnings("unused") public class RxBus { public static final String LOG_BUS = "RXBUS_LOG"; private static volatile RxBus defaultInstance; private Map<Class, List<Disposable>> subscriptionsByEventType = new HashMap<>(); private Map<Object, List<Class>> eventTypesBySubscriber = new HashMap<>(); private Map<Class, List<SubscriberMethod>> subscriberMethodByEventType = new HashMap<>(); private final Subject<Object> bus; private RxBus() { this.bus = PublishSubject.create().toSerialized(); } public static RxBus getDefault() { RxBus rxBus = defaultInstance; if (defaultInstance == null) { synchronized (RxBus.class) { rxBus = defaultInstance; if (defaultInstance == null) { rxBus = new RxBus(); defaultInstance = rxBus; } } } return rxBus; } /** * 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者 * * @param eventType 事件类型 * @return return */ private <T> Flowable<T> toObservable(Class<T> eventType) { return bus.toFlowable(BackpressureStrategy.BUFFER).ofType(eventType); } /** * 根据传递的code和 eventType 类型返回特定类型(eventType)的 被观察者 * * @param code 事件code * @param eventType 事件类型 */ private <T> Flowable<T> toObservable(final int code, final Class<T> eventType) { return bus.toFlowable(BackpressureStrategy.BUFFER).ofType(Message.class) .filter(new Predicate<Message>() { @Override public boolean test(Message o) throws Exception { return o.getCode() == code && eventType.isInstance(o.getObject()); } }).map(new Function<Message, Object>() { @Override public Object apply(Message o) throws Exception { return o.getObject(); } }).cast(eventType); } /** * 注册 * * @param subscriber 订阅者 */ public void register(Object subscriber) { Class<?> subClass = subscriber.getClass(); Method[] methods = subClass.getDeclaredMethods(); for (Method method : methods) { if (method.isAnnotationPresent(Subscribe.class)) { //获得参数类型 Class[] parameterType = method.getParameterTypes(); //参数不为空 且参数个数为1 if (parameterType != null && parameterType.length == 1) { Class eventType = parameterType[0]; addEventTypeToMap(subscriber, eventType); Subscribe sub = method.getAnnotation(Subscribe.class); int code = sub.code(); ThreadMode threadMode = sub.threadMode(); SubscriberMethod subscriberMethod = new SubscriberMethod(subscriber, method, eventType, code, threadMode); addSubscriberToMap(eventType, subscriberMethod); addSubscriber(subscriberMethod); } else if (parameterType == null || parameterType.length == 0) { Class eventType = BusData.class; addEventTypeToMap(subscriber, eventType); Subscribe sub = method.getAnnotation(Subscribe.class); int code = sub.code(); ThreadMode threadMode = sub.threadMode(); SubscriberMethod subscriberMethod = new SubscriberMethod(subscriber, method, eventType, code, threadMode); addSubscriberToMap(eventType, subscriberMethod); addSubscriber(subscriberMethod); } } } } /** * 将event的类型以订阅中subscriber为key保存到map里 * * @param subscriber 订阅者 * @param eventType event类型 */ private void addEventTypeToMap(Object subscriber, Class eventType) { List<Class> eventTypes = eventTypesBySubscriber.get(subscriber); if (eventTypes == null) { eventTypes = new ArrayList<>(); eventTypesBySubscriber.put(subscriber, eventTypes); } if (!eventTypes.contains(eventType)) { eventTypes.add(eventType); } } /** * 将注解方法信息以event类型为key保存到map中 * * @param eventType event类型 * @param subscriberMethod 注解方法信息 */ private void addSubscriberToMap(Class eventType, SubscriberMethod subscriberMethod) { List<SubscriberMethod> subscriberMethods = subscriberMethodByEventType.get(eventType); if (subscriberMethods == null) { subscriberMethods = new ArrayList<>(); subscriberMethodByEventType.put(eventType, subscriberMethods); } if (!subscriberMethods.contains(subscriberMethod)) { subscriberMethods.add(subscriberMethod); } } /** * 将订阅事件以event类型为key保存到map,用于取消订阅时用 * * @param eventType event类型 * @param disposable 订阅事件 */ private void addSubscriptionToMap(Class eventType, Disposable disposable) { List<Disposable> disposables = subscriptionsByEventType.get(eventType); if (disposables == null) { disposables = new ArrayList<>(); subscriptionsByEventType.put(eventType, disposables); } if (!disposables.contains(disposable)) { disposables.add(disposable); } } /** * 用RxJava添加订阅者 * * @param subscriberMethod d */ @SuppressWarnings("unchecked") private void addSubscriber(final SubscriberMethod subscriberMethod) { Flowable flowable; if (subscriberMethod.code == -1) { flowable = toObservable(subscriberMethod.eventType); } else { flowable = toObservable(subscriberMethod.code, subscriberMethod.eventType); } Disposable subscription = postToObservable(flowable, subscriberMethod) .subscribe(new Consumer<Object>() { @Override public void accept(Object o) throws Exception { callEvent(subscriberMethod, o); } }); addSubscriptionToMap(subscriberMethod.subscriber.getClass(), subscription); } /** * 用于处理订阅事件在那个线程中执行 * * @param observable d * @param subscriberMethod d * @return Observable */ private Flowable postToObservable(Flowable observable, SubscriberMethod subscriberMethod) { Scheduler scheduler; switch (subscriberMethod.threadMode) { case MAIN: scheduler = AndroidSchedulers.mainThread(); break; case NEW_THREAD: scheduler = Schedulers.newThread(); break; case CURRENT_THREAD: scheduler = Schedulers.trampoline(); break; default: throw new IllegalStateException("Unknown thread mode: " + subscriberMethod.threadMode); } return observable.observeOn(scheduler); } /** * 回调到订阅者的方法中 * * @param method code * @param object obj */ private void callEvent(SubscriberMethod method, Object object) { Class eventClass = object.getClass(); List<SubscriberMethod> methods = subscriberMethodByEventType.get(eventClass); if (methods != null && methods.size() > 0) { for (SubscriberMethod subscriberMethod : methods) { Subscribe sub = subscriberMethod.method.getAnnotation(Subscribe.class); int c = sub.code(); if (c == method.code && method.subscriber.equals(subscriberMethod.subscriber) && method.method.equals(subscriberMethod.method)) { subscriberMethod.invoke(object); } } } } /** * 是否注册 * * @param subscriber * @return */ public synchronized boolean isRegistered(Object subscriber) { return eventTypesBySubscriber.containsKey(subscriber); } /** * 取消注册 * * @param subscriber object */ public void unregister(Object subscriber) { List<Class> subscribedTypes = eventTypesBySubscriber.get(subscriber); if (subscribedTypes != null) { for (Class<?> eventType : subscribedTypes) { unSubscribeByEventType(subscriber.getClass()); unSubscribeMethodByEventType(subscriber, eventType); } eventTypesBySubscriber.remove(subscriber); } } /** * subscriptions unsubscribe * * @param eventType eventType */ private void unSubscribeByEventType(Class eventType) { List<Disposable> disposables = subscriptionsByEventType.get(eventType); if (disposables != null) { Iterator<Disposable> iterator = disposables.iterator(); while (iterator.hasNext()) { Disposable disposable = iterator.next(); if (disposable != null && !disposable.isDisposed()) { disposable.dispose(); iterator.remove(); } } } } /** * 移除subscriber对应的subscriberMethods * * @param subscriber subscriber * @param eventType eventType */ private void unSubscribeMethodByEventType(Object subscriber, Class eventType) { List<SubscriberMethod> subscriberMethods = subscriberMethodByEventType.get(eventType); if (subscriberMethods != null) { Iterator<SubscriberMethod> iterator = subscriberMethods.iterator(); while (iterator.hasNext()) { SubscriberMethod subscriberMethod = iterator.next(); if (subscriberMethod.subscriber.equals(subscriber)) { iterator.remove(); } } } } public void send(int code, Object o) { bus.onNext(new Message(code, o)); } public void post(Object o) { bus.onNext(o); } public void send(int code) { bus.onNext(new Message(code, new BusData())); } private class Message { private int code; private Object object; public Message() { } private Message(int code, Object o) { this.code = code; this.object = o; } private int getCode() { return code; } public void setCode(int code) { this.code = code; } private Object getObject() { return object; } public void setObject(Object object) { this.object = object; } } }