Multicolaure
Multicolaure

Reputation: 1038

RxJava - Transform a cold observable to hot observable

The problem I want to solve

I am building a kind of MVP (or whatever you call it) where views can subscribe and unsubscribe to the same model.

At start, the view subscribes to the model. The model is empty and the view displays nothing. When calling a method (for instance, when a user clicks), a request is made over the network. The result will populate the model, which will notify the view of the change.

If another view subscribes, it should be notified with the model current value, without any call over the network. If all views unsubscribe while the request is ongoing, the model shall still be popuplated, so that another view can

My attempt

I am using Retrofit with RxJava2 to make the requests over the network, which provides a cold Observable.

For the model, I want to build a hot Observable that returns the last emitted item to any new subscriber. How can I make the hot observable get its emitted items from the cold Observable?

So far, I could achieve this with a BehaviourSubject:

// The same model is provided to all views through a getter
BehaviorSubject<User> model = BehaviorSubject.create();

// Make request
Observable<User> resource = getResourceOverNetwork(3);
resource.subscribe(new Consumer<User>() {
    @Override
    public void accept(@NonNull User user) throws Exception {
        model.onNext(user);
    }
});

This solution feels wrong as I have to manually forward events from the cold Observable to the BehaviourSubject.

Upvotes: 3

Views: 1523

Answers (1)

Multicolaure
Multicolaure

Reputation: 1038

Thanks to your comments, I could successfully implement what I needed with RxRelay.

Create the model:

// The same model is provided to all views through a getter
BehaviorRelay<User> model = BehaviorRelay.create();
    
model.subscribe(view);

Make the requests at any time:

// Make request
Observable<User> resource = getResourceOverNetwork(3);
resource.subscribe(model);
    
// Make a new request
getResourceOverNetwork(4).subscribe(model);

It is much easier now and much cleaner. Thanks a lot!

Upvotes: 1

Related Questions