RxJava Relay vs Subjects
Asked Answered
P

4

20

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
}
Polyhydroxy answered 5/8, 2017 at 6:2 Comment(0)
F
12

subscribe has overloads and, usually, people get used to the subscribe(Consumer) overload. Then they use subjects and suddenly onComplete is also invoked. RxRelay saves the user from themselves who don't think about the difference between subscribe(Consumer) and subscribe(Observer).

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

Indeed, but based on our experience with beginners, they often don't think about this or even know about the available methods to consider.

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

If you need a way to send items into the subject, this doesn't work. The purpose is to use the subject to perform item multicasting, sometimes from another Observable. If you are in full control of the emissions through the Subject, you should have the decency of not calling onComplete and not letting anything else do it either.

Feverous answered 5/8, 2017 at 10:0 Comment(4)
Thanks akarnokd, Good to know I'm not missing anything :) Regarding #2 if you put your subject inside wrapper class you can have a method accept(item) { subject.omNext(item) }. And The Subject remains a private fieldPolyhydroxy
Are you sure this is the only reason though?. Creating a whole new library just to avoid a beginners mistake seems like an overkill. So is importing it to your projectsPolyhydroxy
You mean this? Since the internals are mostly the same as the standard Subjects, and removing the terminal event handling is not a significant performance win with either, that leaves us with what I wrote.Feverous
Yes ! I opened that issue after reading your answer :) thanksPolyhydroxy
S
2

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)

Ssr answered 29/8, 2020 at 4:3 Comment(0)
E
1

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.

Engram answered 13/11, 2020 at 23:46 Comment(0)
A
-2

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);
}
Ankylosis answered 29/1, 2019 at 6:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.