rxjava 观察者模式: RxRelay 与 Subject、rxbus

一、Relay

JakeWharton/RxRelay

relay 英 [ˈriːleɪ] 美 [ˈriːleɪ]
v. 接转,转送,转发(信息、消息等); 播放,转播(电视或广播讯号);
n. 接力赛; 接班的人(或动物); 轮换者; 中继设备

Rxrelay:既是一个Observable 也是 一个Consumer的RxJava。
基本上可以当做是一个除了无法调用onComplete或onError之外的Subject。
使用它的好处就是不必担心事件在onComplete或者onError后终止事件订阅关系,
它允许将非Rx API连接到Rx,而不用担心意外触发终端状态(onComplete或者onError)。

package com.jakewharton.rxrelay2;

/**
 * Represents a Consumer and an Observable at the same time, allowing
 * multicasting events from a single source to multiple child Observers.
 * <p>All methods except {@link #accept} are thread-safe.
 * Use {@link #toSerialized()} to make it thread-safe as well.
 *
 * @param <T> the item value type
 */
// 同时代表一个消费者和一个可观察对象,
// 从而允许将事件从单个源多播到多个子观察者。 
// 除{@link #accept}之外的所有方法都是线程安全的。 
// 使用{@link #toSerialized()}使其也成为线程安全的。
//
public abstract class Relay<T> extends Observable<T> implements Consumer<T> {
    /** {@inheritDoc} */
    @Override public abstract void accept(@NonNull T value); 
    // Redeclare without checked exception.

    /**
     * Returns true if the subject has any Observers.
     * <p>The method is thread-safe.
     */
    public abstract boolean hasObservers();

    /**
     * Wraps this Relay and serializes the calls to {@link #accept}, making it thread-safe.
     * <p>The method is thread-safe.
     */
    @NonNull
    @CheckReturnValue
    public final Relay<T> toSerialized() {
        if (this instanceof SerializedRelay) {
            return this;
        }
        return new SerializedRelay<T>(this);
    }
}

在这里插入图片描述

PublishRelay:只接受订阅后的事件

PublishRelay<Object> relay = PublishRelay.create();
// observer1 will receive all events
relay.subscribe(observer1);//一经注册,后续都可接收
relay.accept("one");
relay.accept("two");
// observer2 will only receive "three"
relay.subscribe(observer2);
relay.accept("three");

ReplayRelay:接受订阅前和订阅后的所有事件

ReplayRelay<Object> relay = new ReplayRelay<>();
relay.accept("one");
relay.accept("two");
relay.accept("three");

// both of the following will get the values from above
relay.subscribe(observer1);//先发送,再注册:也可接收到
relay.subscribe(observer2);

BehaviorRelay:他会接收订阅之前的最后一个事件和订阅之后的事件

// observer will receive all events.
BehaviorRelay<Object> subject = BehaviorRelay.create("default");
subject.subscribe(observer);
subject.accept("one");
subject.accept("two");
subject.accept("three");

// observer will receive the "one", "two" and "three" events, but not "zero"
BehaviorRelay<Object> subject = BehaviorRelay.create("default");
subject.accept("zero");
subject.accept("one");
subject.subscribe(observer);
subject.accept("two");
subject.accept("three");

二、Subject

package io.reactivex.subjects;

/**
 * Represents an {@link Observer} and an {@link Observable} at the same time, allowing
 * multicasting events from a single source to multiple child {@code Observer}s.
 * <p>
 * All methods except the {@link #onSubscribe(io.reactivex.disposables.Disposable)},
 * {@link #onNext(Object)},
 * {@link #onError(Throwable)} and {@link #onComplete()} are thread-safe.
 * Use {@link #toSerialized()} to make these methods thread-safe as well.
 *
 */
//同时代表一个{@link Observer}和{@link Observable},
//从而允许将事件从单个源多播到多个子{@code Observer}。 
//所有除了
//{@link #onSubscribe(io.reactivex.disposables.Disposable)},
//{@link #onNext(Object)}, 
//{@link #onError(Throwable)}和{@link# onComplete()}是线程安全的。 
//使用{@link #toSerialized()}也可以使这些方法成为线程安全的。
//
public abstract class Subject<T> extends Observable<T> implements Observer<T> {
    /**
     * Returns true if the subject has any Observers.
     * <p>The method is thread-safe.
     * @return true if the subject has any Observers
     */
    public abstract boolean hasObservers();

    /**
     * Returns true if the subject has reached a terminal state through an error event.
     * <p>The method is thread-safe.
     * @return true if the subject has reached a terminal state through an error event
     * @see #getThrowable()
     * @see #hasComplete()
     */
    public abstract boolean hasThrowable();

    /**
     * Returns true if the subject has reached a terminal state through a complete event.
     * <p>The method is thread-safe.
     * @return true if the subject has reached a terminal state through a complete event
     * @see #hasThrowable()
     */
    public abstract boolean hasComplete();

    /**
     * Returns the error that caused the Subject to terminate or null if the Subject
     * hasn't terminated yet.
     * <p>The method is thread-safe.
     * @return the error that caused the Subject to terminate or null if the Subject
     * hasn't terminated yet
     */
    @Nullable
    public abstract Throwable getThrowable();

    /**
     * Wraps this Subject and serializes the calls to the onSubscribe, onNext, onError and
     * onComplete methods, making them thread-safe.
     * <p>The method is thread-safe.
     * @return the wrapped and serialized subject
     */
    @NonNull
    public final Subject<T> toSerialized() {
        if (this instanceof SerializedSubject) {
            return this;
        }
        return new SerializedSubject<T>(this);
    }
}

在这里插入图片描述

PublishSubject :只接受订阅后的事件

PublishSubject<Object> subject = PublishSubject.create();
// observer1 will receive all onNext and onComplete events
subject.subscribe(observer1);
subject.onNext("one");
subject.onNext("two");
// observer2 will only receive "three" and onComplete
subject.subscribe(observer2);
subject.onNext("three");
subject.onComplete();

// late Observers only receive the terminal event
subject.test().assertEmpty();

ReplaySubject :接受订阅前和订阅后的所有事件

ReplaySubject<Object> subject = ReplaySubject.create();
subject.onNext("one");
subject.onNext("two");
subject.onNext("three");
subject.onComplete();

// both of the following will get the onNext/onComplete calls from above
subject.subscribe(observer1);//先发送,再注册,也能收到
subject.subscribe(observer2);

BehaviorSubject :他会接收订阅之前的最后一个事件和订阅之后的事件。

// observer will receive all 4 events (including "default").
BehaviorSubject<Object> subject = BehaviorSubject.createDefault("default");
subject.subscribe(observer);//订阅
subject.onNext("one");
subject.onNext("two");
subject.onNext("three");

// observer will receive the "one", "two" and "three" events, but not "zero"
BehaviorSubject<Object> subject = BehaviorSubject.create();
subject.onNext("zero");
subject.onNext("one");
subject.subscribe(observer);//订阅
subject.onNext("two");
subject.onNext("three");

// observer will receive only onComplete
BehaviorSubject<Object> subject = BehaviorSubject.create();
subject.onNext("zero");
subject.onNext("one");
subject.onComplete();
subject.subscribe(observer);//订阅

// observer will receive only onError
BehaviorSubject<Object> subject = BehaviorSubject.create();
subject.onNext("zero");
subject.onNext("one");
subject.onError(new RuntimeException("error"));
subject.subscribe(observer);//订阅
subject.accept("three");

SerializedSubject :
序列化对Observer方法的调用。 所有其他Observable和Subject方法在设计上都是线程安全的。

三、 RxRelay 与 Subject区别:

public abstract class Subject<T> extends Observable<T> implements Observer<T> {...}

public abstract class Relay<T> extends Observable<T> implements Consumer<T> {...}

由上图可见 RxRelay 与 Subject区别 即是 Consumer和Observer区别:
在这里插入图片描述

在这里插入图片描述

四、 简单的 RxBus 与 Subject

import io.reactivex.Observable;
import io.reactivex.subjects.PublishSubject;
import io.reactivex.subjects.Subject;

public class RxBus {

    private static volatile Subject<Object> instance;

    private RxBus() {
        instance = PublishSubject.create().toSerialized();
    }

    private static class Holder {
        private static final RxBus BUS = new RxBus();
    }

    public static RxBus getDefault() {
        return Holder.BUS;
    }

    public void post(Object obj) {
        instance.onNext(obj);
    }

    public <T> Observable<T> toObservable(Class<T> tClass) {
        return instance.ofType(tClass);
    }

    public Observable<Object> toObservable() {
        return instance;
    }

    public boolean hasObservers() {
        return instance.hasObservers();
    }
}

测试:

public void test() {
    //发送
    RxBus.getDefault().post(new String("111"));

    //接收
    CompositeDisposable compositeDisposable = new CompositeDisposable();
    Disposable disposable = RxBus.getDefault()
            .toObservable(String.class)
            .toFlowable(BackpressureStrategy.BUFFER)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {

                }
            });
    compositeDisposable.add(disposable);
    if (!compositeDisposable.isDisposed()) {//避免内存泄漏
        compositeDisposable.dispose();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值