Preface
Rxbus is also unavoidable because of the recent learning of RxJava2, but there are still great changes from RxJava1 to RxJava2. For example, in 2.x, Observable does not support backpressure, and a new Flowable will be used to support backpressure. Consumer and BiConsumer have replaced Action1 and Action2, Function has replaced Func1, and BiFunction has replaced Func 2.N. And they all add throws Exception, which means that Mom no longer has to worry about trying-catch when we do something. So our previous RxBus based on Rxjava1 needs to be upgraded.
RxBus Version 1
For RxJava 1.x.x, I believe that everyone is familiar with it, and RxBus is not a word. Here is RxJava I used in RxJava 1 version, with detailed comments in the code. There's not much to say here!
- RxBus1
public class RxBus {
// private static volatile RxBus mInstance;
private SerializedSubject<Object, Object> mSubject;
private HashMap<String, CompositeSubscription> mSubscriptionMap;
/**
*
* 1,Subject It also acts as Observer and Observable. Subject is non-thread-safe. To avoid this problem,
* Subject needs to be converted to a Serialized Subject, and thread-insecure PublishSubject is wrapped in the class as thread-safe Subject.
* 2,PublishSubject Data from the original Observable will only be sent to the observer after the time point at which the subscription occurs.
*
*/
public RxBus() {
mSubject = new SerializedSubject<>(PublishSubject.create());
}
// Here we use Dagger to handle singletons
/*
private RxBus() {
mSubject = new SerializedSubject<>(PublishSubject.create());
}
public static RxBus getInstance() {
if (mInstance == null) {
synchronized (RxBus.class) {
if (mInstance == null) {
mInstance = new RxBus();
}
}
}
return mInstance;
}*/
/**
* Send events
*
* @param o
*/
public void post(Object o) {
mSubject.onNext(o);
}
/**
* Returns an Observable instance of the specified type
* 1,ofType The operator emits only the specified type of data, and inside it is filter+cast
* @param type
* @param <T>
* @return
*/
public <T> Observable<T> toObservable(final Class<T> type) {
return mSubject.ofType(type);
}
/**
* Is there an observer subscription?
*
* @return
*/
public boolean hasObservers() {
return mSubject.hasObservers();
}
/**
* A default subscription method
*
* @param type
* @param next
* @param error
* @param <T>
* @return
*/
public <T> Subscription doSubscribe(Class<T> type, Action1<T> next, Action1<Throwable> error) {
return toObservable(type)
// Add back pressure treatment, otherwise there will be abnormalities in some places. For back pressure reference here: https://gold.xitu.io/post/582d413c8ac24700619cceed
.onBackpressureBuffer()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(next, error);
}
/**
* Save subscription after subscription
* @param o
* @param subscription
*/
public void addSubscription(Object o, Subscription subscription) {
if (mSubscriptionMap == null) {
mSubscriptionMap = new HashMap<>();
}
String key = o.getClass().getName();
if (mSubscriptionMap.get(key) != null) {
mSubscriptionMap.get(key).add(subscription);
} else {
// Represents a set of subscriptions, subscribing unsubscribed together
CompositeSubscription compositeSubscription = new CompositeSubscription();
compositeSubscription.add(subscription);
mSubscriptionMap.put(key, compositeSubscription);
}
}
/**
* unsubscribe
* @param o
*/
public void unSubscribe(Object o) {
if (mSubscriptionMap == null) {
return;
}
String key = o.getClass().getName();
if (!mSubscriptionMap.containsKey(key)){
return;
}
if (mSubscriptionMap.get(key) != null) {
mSubscriptionMap.get(key).unsubscribe();
}
mSubscriptionMap.remove(key);
}
}
RxBus Version 2
Before that, let's familiarize ourselves with the principles of EventBus and RxJava. Here's just a brief chat:
EventBus
EventBus is an efficient publish/subscribe event bus mechanism under Android. It is a publish/subscribe design pattern (Publish/Subsribe), or an observer design pattern.
RxJava
The asynchronous implementation of RxJava is implemented through an extended observer pattern. RxJava has four basic concepts: Observable, Observer, subscribe and event. Observable and Observer implement the subscribe relationship through subscribe() method, so that Observable can send out events to notify Observer when needed.
Understanding what the observer model is, we can better transform RxBbus1 into the RxBus2 we need.
- RxBus2
Looking through the Rxjava2 documentation, we know that there is no Serialized Subject class in RxJava2. We can call the toSerialized() method to wrap and serialize the Subject to make it thread-safe. Because Rxjava2 uses Flowable to support backpressure, we can convert it into a Flowable instance with backpressure. Basically, that's the difference between bus1 and bus2!
public class RxBus {
private HashMap<String, CompositeDisposable> mSubscriptionMap;
private static volatile RxBus mRxBus;
private final Subject<Object> mSubject;
//Single column mode
public static RxBus getIntanceBus(){
if (mRxBus==null){
synchronized (RxBus.class){
if(mRxBus==null){
mRxBus = new RxBus();
}
}
}
return mRxBus;
}
public RxBus(){
mSubject = PublishSubject.create().toSerialized();
}
public void post(Object o){
mSubject.onNext(o);
}
/**
* Returns a Flowable instance with backpressure of the specified type
*
* @param <T>
* @param type
* @return
*/
public <T>Flowable<T> getObservable(Class<T> type){
return mSubject.toFlowable(BackpressureStrategy.BUFFER)
.ofType(type);
}
/**
* A default subscription method
*
* @param <T>
* @param type
* @param next
* @param error
* @return
*/
public <T> Disposable doSubscribe(Class<T> type, Consumer<T> next, Consumer<Throwable> error){
return getObservable(type)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(next,error);
}
/**
* Is there an observer subscription?
*
* @return
*/
public boolean hasObservers() {
return mSubject.hasObservers();
}
/**
* disposable after saving subscription
* @param o
* @param disposable
*/
public void addSubscription(Object o, Disposable disposable) {
if (mSubscriptionMap == null) {
mSubscriptionMap = new HashMap<>();
}
String key = o.getClass().getName();
if (mSubscriptionMap.get(key) != null) {
mSubscriptionMap.get(key).add(disposable);
} else {
//One-time containers can hold multiple containers and provide additions and removals.
CompositeDisposable disposables = new CompositeDisposable();
disposables.add(disposable);
mSubscriptionMap.put(key, disposables);
}
}
/**
* unsubscribe
* @param o
*/
public void unSubscribe(Object o) {
if (mSubscriptionMap == null) {
return;
}
String key = o.getClass().getName();
if (!mSubscriptionMap.containsKey(key)){
return;
}
if (mSubscriptionMap.get(key) != null) {
mSubscriptionMap.get(key).dispose();
}
mSubscriptionMap.remove(key);
}
}
- Use
Send events
RxBus rxBus = RxBus.getIntanceBus();
//Send events
rxBus.post(new RxBusMessage("1"));
rxBus.post(new RxBusMessage("2"));
Acceptance of events
private void initRxBus() {
rxBus = RxBus.getIntanceBus();
registerRxBus(RxBusMessage.class, new Consumer<RxBusMessage>() {
@Override
public void accept(@NonNull RxBusMessage rxBusMessage) throws Exception {
//Processing according to event type
if(TextUtils.equals(rxBusMessage.getMessage(),"1")){
mTvRebus.setText(rxBusMessage.getMessage());
}else if(TextUtils.equals(rxBusMessage.getMessage(),"2")){
rx2.setText(rxBusMessage.getMessage());
}
}
});
}
//register
public <T> void registerRxBus(Class<T> eventType, Consumer<T> action) {
Disposable disposable = rxBus.doSubscribe(eventType, action, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
Log.e("NewsMainPresenter", throwable.toString());
}
});
rxBus.addSubscription(this,disposable);
}
Destruction incidents
public void unregisterRxBus() {
rxBus.unSubscribe(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterRxBus();
}
Effect
Last
Please correct what is wrong! Let's make progress together!