RxBus的封裝

要實現fragment與activity之前的通訊,或者service與activity的通訊,我們可以有好幾種方式實現

1、廣播

2、回調接口

3、eventBus、RxBus

4、其他

 

 

封裝了一下RxBus的使用,廢話不多說,直接上源碼:

1、ThreadMode,所執行的線程

public enum ThreadMode {
    /**
     * current thread
     */
    CURRENT_THREAD,

    /**
     * android main thread
     */
    MAIN,


    /**
     * new thread
     */
    NEW_THREAD
}

2、Subscribe,註解

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Subscribe {
    int code() default -1;

    ThreadMode threadMode() default ThreadMode.CURRENT_THREAD;
}

3、SubscriberMethod,存儲訂閱者的相關信息,並提供invoke調用

public class SubscriberMethod {
    public Method method;
    public ThreadMode threadMode;
    public Class<?> eventType;
    public Object subscriber;
    public int code;
    public boolean originalIsPrimitive;//原始類型是否爲基本類型

    public SubscriberMethod(Object subscriber, Method method, Class<?> eventType, int code, ThreadMode threadMode, boolean originalIsPrimitive) {
        this.method = method;
        this.threadMode = threadMode;
        this.eventType = eventType;
        this.subscriber = subscriber;
        this.code = code;
        this.originalIsPrimitive = originalIsPrimitive;
    }


    /**
     * 調用方法
     *
     * @param o 參數
     */
    public void invoke(Object o) {
        try {
            Class[] parameterType = method.getParameterTypes();
            if (parameterType != null && parameterType.length == 1) {
                method.invoke(subscriber, o);
            } else if (parameterType == null || parameterType.length == 0) {
                method.invoke(subscriber);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

4、PrimitiveBox,基本類型轉換成對象類型

public class PrimitiveBox {

    /**
     * 裝箱
     *
     * @param target 目標類
     * @return 轉換後的Class
     */
    public static Class<?> mantle(final Class<?> target) {
        if (boolean.class.equals(target)) {
            return Boolean.class;
        } else if (char.class.equals(target)) {
            return Character.class;
        } else if (byte.class.equals(target)) {
            return Byte.class;
        } else if (short.class.equals(target)) {
            return Short.class;
        } else if (int.class.equals(target)) {
            return Integer.class;
        } else if (long.class.equals(target)) {
            return Long.class;
        } else if (float.class.equals(target)) {
            return Float.class;
        } else if (double.class.equals(target)) {
            return Double.class;
        } else {
            return target;
        }
    }
}

5、BusData,默認的事件類型

public class BusData {
    String id;
    String status;
    public BusData() {}
    public BusData(String id, String status) {
        this.id = id;
        this.status = status;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

6、RxBus,核心類

public class RxBus {
    public static final String TAG = "RxBus_log";
    private static volatile RxBus defaultInstance;

    /**
     * key==》訂閱者對象,value==》訂閱事件(disposable )
     */
    private Map<Object, List<Disposable>> subscriptionsByEventType = new HashMap<>();

    /**
     * key==》訂閱者對象,value==》事件類型
     * <p>
     * value是 根據Key所註解的方法的參數類型確定,默認==》BusData,如:
     * <p>
     * 註解方法==》a(),則value==》BusData
     * 註解方法==》a(String str),則value==》String
     */
    private Map<Object, List<Class>> eventTypesBySubscriber = new HashMap<>();

    /**
     * key==》事件類型,value==》訂閱者信息
     * <p>
     * value信息包括:訂閱者對象(subscriber), 方法名(method), 事件類型(eventType), 事件code(code), 線程類型(threadMode)
     */
    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;
    }

    /**
     * 註冊
     *
     * @param subscriber 訂閱者
     */
    public void register(Object subscriber) {
        YLogUtil.logD2Tag(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@註冊@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@--訂閱者對象", 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];
                    executeRegistered(subscriber, method, eventType);

                } else if (parameterType == null || parameterType.length == 0) {

                    Class eventType = BusData.class;
                    executeRegistered(subscriber, method, eventType);

                }
            }
        }
        YLogUtil.logD2Tag(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@註冊完成@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@--訂閱者對象", subscriber);
    }

    /**
     * 取消註冊
     *
     * @param subscriber 訂閱者
     */
    public void unregister(Object subscriber) {
        YLogUtil.logD2Tag(TAG, "###################################取消註冊###################################--訂閱者對象", subscriber);
        //通過訂閱者對象,獲取對應的事件類型集合
        List<Class> subscribedTypes = eventTypesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class<?> eventType : subscribedTypes) {
                unSubscribeByEventType(subscriber);
                unSubscribeMethodByEventType(subscriber, eventType);
                YLogUtil.logD2Tag(TAG, "執行取消註冊--訂閱者對象", subscriber, "事件類型", eventType);
            }
            eventTypesBySubscriber.remove(subscriber);
        }
        YLogUtil.logD2Tag(TAG, "###################################取消註冊完成###############################--訂閱者對象", subscriber);
    }

    /**
     * 是否註冊
     *
     * @param subscriber 訂閱者
     * @return
     */
    public synchronized boolean isRegistered(Object subscriber) {
        boolean isRegistered = eventTypesBySubscriber.containsKey(subscriber);
        YLogUtil.logD2Tag(TAG, "************************************判斷是否註冊******************************--訂閱者對象", subscriber, "是?", isRegistered);
        return isRegistered;
    }

    /**
     * 執行註冊
     *
     * @param subscriber 訂閱者對象
     * @param method     方法名
     * @param eventType  事件類型
     */
    private void executeRegistered(Object subscriber, Method method, Class eventType) {
        //判斷是否爲基本類型
        boolean isPrimitive = eventType.isPrimitive();
        if (isPrimitive) {
            YLogUtil.logD2Tag(TAG, "*********基礎類型自動裝箱---開始*********裝箱前類型", eventType);
            eventType = PrimitiveBox.mantle(eventType);
            YLogUtil.logD2Tag(TAG, "*********基礎類型自動裝箱---完成*********裝箱後類型", eventType);
        }
        // key==》訂閱者對象,value==》事件類型,保存到map裏
        addEventTypeToMap(subscriber, eventType);

        //獲取註解
        Subscribe sub = method.getAnnotation(Subscribe.class);
        int code = sub.code();
        ThreadMode threadMode = sub.threadMode();

        //key==》事件類型,value==》訂閱者信息,保存到map裏
        SubscriberMethod subscriberMethod = new SubscriberMethod(subscriber, method, eventType, code, threadMode, isPrimitive);
        addSubscriberToMap(eventType, subscriberMethod);

        //添加到RxJava訂閱
        addSubscriber(subscriberMethod);

        YLogUtil.logD2Tag(TAG, "執行註冊---方法:", method, "---事件類型:", eventType);
    }

    /**
     * key==》訂閱者對象,value==》事件類型,保存到map裏
     *
     * @param subscriber 訂閱者對象
     * @param eventType  事件類型
     */
    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);
        }
    }

    /**
     * key==》事件類型,value==》訂閱者信息,保存到map裏
     *
     * @param eventType        事件類型
     * @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);
        }
    }


    /**
     * 用RxJava添加訂閱者
     *
     * @param subscriberMethod 訂閱者信息
     */
    @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);
                    }
                });
        //key==》訂閱者對象,value==》訂閱事件(disposable )
        addSubscriptionToMap(subscriberMethod.subscriber, subscription);
    }

    /**
     * 根據傳遞的 eventType 類型返回特定類型(eventType)的 被觀察者
     *
     * @param eventType 事件類型
     * @return return
     */
    public <T> Flowable<T> toObservable(Class<T> eventType) {
        //ofType(class)  指定某個類型的class,過濾屬於這個類型的的結果,其它拋棄
        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) {
        //ofType(class)  指定某個類型的class,過濾屬於這個類型的的結果,其它拋棄
        return bus.toFlowable(BackpressureStrategy.BUFFER).ofType(Message.class)
                //採用filter()變換操作符
                .filter(new Predicate<Message>() {
                    // 根據test()的返回值 對被觀察者發送的事件進行過濾 & 篩選
                    // a. 返回true,則繼續發送
                    // b. 返回false,則不發送(即過濾)
                    @Override
                    public boolean test(Message o) throws Exception {
                        return o.getCode() == code && eventType.isInstance(o.getObject());
                    }
                    // map操作符,Function<Object,Object>,只要類型爲Object的子類就可以進行轉換
                }).map(new Function<Message, Object>() {
                    @Override
                    public Object apply(Message o) throws Exception {
                        return o.getObject();
                    }
                }).cast(eventType);
    }

    /**
     * 用於處理訂閱事件在那個線程中執行
     *
     * @param observable       訂閱事件
     * @param subscriberMethod 訂閱者信息
     * @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);
    }

    /**
     * key==》訂閱者對象,value==》訂閱事件(disposable )
     *
     * @param subscriber 訂閱者對象
     * @param disposable 訂閱事件
     */
    private void addSubscriptionToMap(Object subscriber, Disposable disposable) {
        List<Disposable> disposables = subscriptionsByEventType.get(subscriber);
        if (disposables == null) {
            disposables = new ArrayList<>();
            subscriptionsByEventType.put(subscriber, disposables);
        }
        if (!disposables.contains(disposable)) {
            disposables.add(disposable);
        }
    }


    /**
     * 回調到訂閱者的方法中
     *
     * @param subscriberMethod 訂閱者信息
     * @param object           事件類型對象
     */
    private void callEvent(SubscriberMethod subscriberMethod, Object object) {
        YLogUtil.logD2Tag(TAG, "執行回調----訂閱者對象", subscriberMethod.subscriber, "方法", subscriberMethod.method, "事件類型對象", object);
        //因爲最終發送的爲事件類型對象
        //所以需要通過事件類型對象,獲取對應的事件類型
        Class eventClass = object.getClass();
        //通過事件類型,獲取訂閱者信息
        List<SubscriberMethod> subscriberMethodList = subscriberMethodByEventType.get(eventClass);
        //判斷訂閱者信息是否相同,並回調訂閱者
        if (subscriberMethodList != null && subscriberMethodList.size() > 0) {
            for (SubscriberMethod tmpSubscriberMethod : subscriberMethodList) {
                if (tmpSubscriberMethod.code == subscriberMethod.code && subscriberMethod.subscriber.equals(tmpSubscriberMethod.subscriber)
                        && subscriberMethod.method.equals(tmpSubscriberMethod.method)) {
                    tmpSubscriberMethod.invoke(object);
                    YLogUtil.logD2Tag(TAG, "回調成功----訂閱者對象", subscriberMethod.subscriber, "方法", subscriberMethod.method, "事件類型對象", object);
                }

            }
        }
    }

    /**
     * 移除訂閱者對象對應的訂閱事件
     *
     * @param subscriber 訂閱者對象
     */
    private void unSubscribeByEventType(Object subscriber) {
        List<Disposable> disposables = subscriptionsByEventType.get(subscriber);
        if (disposables != null) {
            Iterator<Disposable> iterator = disposables.iterator();
            while (iterator.hasNext()) {
                Disposable disposable = iterator.next();
                if (disposable != null && !disposable.isDisposed()) {
                    disposable.dispose();
                    iterator.remove();
                }
            }
        }
    }

    /**
     * 移除訂閱者對象對應的訂閱者信息
     *
     * @param subscriber 訂閱者對象
     * @param 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) {
        Message message = new Message(code, o);
        bus.onNext(message);
        YLogUtil.logD2Tag(TAG, "發送RxBus", o);
    }

    public void post(Object o) {
        bus.onNext(o);
    }

    public void send(int code) {
        Message message = new Message(code, new BusData());
        bus.onNext(message);
        YLogUtil.logD2Tag(TAG, "發送RxBus", message.object);
    }

    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;
        }
    }
}

 

RxBus使用方式

一、註冊RxBus:

public class TestActivity extends Activity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        RxBus.getDefault().register(this);
    }


    @SuppressLint("測試1,參數爲String類型")
    @Subscribe(code = 1001, threadMode = ThreadMode.MAIN)
    public void rxBusTest1(String msg) {
       
    }

    @SuppressLint("測試2,參數爲int基本數據類型")
    @Subscribe(code = 1002, threadMode = ThreadMode.MAIN)
    public void rxBusTest2(int type) {
       
    }

    @SuppressLint("測試3,參數爲自定義對象")
    @Subscribe(code = 1003, threadMode = ThreadMode.MAIN)
    public void rxBusTest3(MsgData msgData) {
       
    }


    @SuppressLint("測試4,無參")
    @Subscribe(code = 1004, threadMode = ThreadMode.MAIN)
    public void rxBusTest4() {
       
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        
        RxBus.getDefault().unregister(this);
    }

}

二、發送RxBus:

RxBus.getDefault().send(1001,"hihi");

RxBus.getDefault().send(1002,123);

RxBus.getDefault().send(1003,new MsgData(111,"test"));

RxBus.getDefault().send(1004);

 

public class MsgData {
    public int code;
    public String msg;

    public MsgData (int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}

 

混淆:

#如RxBus所在包名爲com.cn.rxbus

#Rxbus混淆
-dontwarn com.cn.rxbus.**
-keep class com.cn.rxbus.** { *;}
-keepattributes *Annotation
-keep @com.cn.rxbus.Subscribe class * {*;}
-keep class * {
    @com.cn.rxbus.Subscribe <fields>;
}
-keepclassmembers class * {
    @com.cn.rxbus.Subscribe <methods>;
}
#Rxbus混淆end

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章