RxJava Relay vs Subjects

Viewed 8221

I'm trying to understand the purpose of this library by Jake Warthon: https://github.com/JakeWharton/RxRelay

Basically: A Subject except without the ability to call onComplete or onError. Subjects are stateful in a damaging way: when they receive an onComplete or onError they no longer become usable for moving data.

I get idea, it's a valid use case, but the above seems easy to achieve just using the existing subjects.

1. Don't forward errors/completions events to the subject:

`observable.subscribe({ subject.onNext(it) }, { log error / throw exception },{ ... })`

2. Don't expose the subject, make your method signature return an observable instead.

fun(): Observable<> { return subject }

I'm obviously missing something here and I'm very curios on what it is!

class MyPublishRelay<I> : Consumer<I> {

    private val subject: Subject<I> = PublishSubject.create<I>()

    override fun accept(intent: I) = subject.onNext(intent)

    fun subscribe(): Disposable = subject.subscribe()
    fun subscribe(c: Consumer<in I>): Disposable = subject.subscribe(c)
    //.. OTHER SUBSCRIBE OVERLOADS
}
4 Answers

Subjects have far more overhead because they have to track and handle terminal event states. Relays are stateless aside from subscription management.

- Jake Wharton

(This is from the issue OP opened on GitHub and felt it was a more a correct answer and wanted to "relay" it here for others to see. https://github.com/JakeWharton/RxRelay/issues/30)

In addition to @akarnokd answer:

In some cases you can't control the flow of data inside the Observable, an example of this is when observing data changes from a database table using Room Database.

If you use Subjects, executing subjects.getValue will always throw error about null safety. So you have to put "? or !!" everywhere in your code even though you know that it will be not nullable.

public T getValue() {
    Object o = value.get();
    if (NotificationLite.isComplete(o) || NotificationLite.isError(o)) {
        return null;
    }
    return NotificationLite.getValue(o);
}
Related