Mes
Mes

Reputation: 1691

How to Resubscribe to Observables

I have a bottom bar with four tabs. Each tab is a Fragment. I want to stop any network calls when user moves to another Fragment so I'm adding all Observable calls to a CompositeSubscription and I unsubscribe from them in onDestroyView(). Next time user enters the screen all network calls fail (since I have unsubscribed) so I want to subscribe again.

I'm not sure how I am supposed to do this : somehow I have to re-subscribe when onResume()/onViewAttached() is called for the Fragment. I'm using RxJava 1.

Edit : I have checked similar questions and their answers mention cache and replay operators but I don't think that's the case cause they were asking to also get the previously emitted items, while I just want to be able to perform again any network calls.

This is how I'm subscribing to an Observable for a network call :

            subscriptions.add(remoteDataSource.getFeedMore(localDataSource.getFirstStoredId())
                .doOnNext(new Action1<FeedItemsRequestDetailsWrapper>() {
                    @Override
                    public void call(FeedItemsRequestDetailsWrapper wrapper) {
                        if (wrapper != null) {
                            localDataSource.saveFeed(wrapper.getFeedItemList());
                            localDataSource.saveServerState(wrapper.getFeedRequestDetails());
                        }
                    }
                })
                .subscribeOn(schedulerProvider.io())
                .observeOn(schedulerProvider.mainThread())
                .subscribe(new Action1<FeedItemsRequestDetailsWrapper>() {
                    @Override
                    public void call(FeedItemsRequestDetailsWrapper wrapper) {
                        // call to View to update
                    }
                }));

And how I unsubscribe :

@Override
public void unsubscribe() {
    if (subscriptions != null && subscriptions.hasSubscriptions()) {
        subscriptions.unsubscribe();
    }
}

Example Use Case : user enters Timeline screen, user clicks a button and a network call is executed ( modeled as an Observable in my Presenter class like the code I posted right above ). Then user exits this screen ( onDestroyView() is called and any subscriptions are unsubscribed). Some time later user enters Timeline screen again and clicks the button.

This is when I receive HTTP FAILED: java.io.IOException: Canceled cause I have unsubscribed and I want to re-subscribe again so I can execute the network call without errors.

Thanks

Upvotes: 0

Views: 731

Answers (1)

Gunhan
Gunhan

Reputation: 7045

Update

If you call unsubscribe in CompositeSubscrition you can't add new subscriptions to it again. If you want to use the same composite instance again, then you need to call subscriptions.clear() or you can create a new instance when the fragment is initialized.

Prev

First things first, if you unsubscribe from any observable/stream/flowable etc. you gonna lose the any incoming data/events.

If you want to get the latest result of an subscription then obviously you should do it before unsubscribe happens.

The problem here is your subscriptions should not be dependant on any Fragment or Activity lifecycle unless it's totally finished/destroyed.

So if you know that you have long requests you should subscribe them on a android.app.Service.

Then you will face another problem communicating back and forth between Services and Fragments/Activities.

The easy solution on your case is you can create a BehaviourSubject in a singleton class (better to use Dagger to inject that model to both fragment and service). Then in your Service subscribe to your long running stream and publish the next events to that BehaviourSubject

BehaviourSubject saves the last emitted data. So next time you subscribe them in your newly created fragment it will start with the last emitted item.

Of course this answer just cover one use-case according to your needs you may need to do something else.

Upvotes: 1

Related Questions