3

I'm using Retrofit 2 with RxAndroid, and I want to keep a request going during a config change. I thought I could do it with Observable.cache() as described in this blog post and others I've seen, but the following flow causes an InterruptedException.

Observable<Result<List<Post>>> request = 
        postService.index(page).cache();
Subscription subscribeOne = request.subscribe();
subscribeOne.unsubscribe();
Subscription subscribeTwo = request.subscribe();

I'm pretty sure the following code in the Retrofit source is responsible for cancelling the request when unsubscribe is called.

// Attempt to cancel the call if it is still in-flight on unsubscription.
subscriber.add(Subscriptions.create(new Action0() {
    @Override public void call() {
        call.cancel();
    }
}));

Not unsubscribing makes everything work, but this could cause leaks. Has anyone managed to handle config changes with Retrofit 2? Is there a different approach I can use?

Jimeux
  • 2,956
  • 1
  • 18
  • 14

2 Answers2

1

Thanks to a hint from /u/insane-cabbage, I managed to implement this with a BehaviourSubject (safely encapsulated in a presenter). Here's an example of the flow.

BehaviorSubject<String> subject = BehaviorSubject.create();

/** User loads view and network request begins */
Observable.just("value")
        .delay(200, TimeUnit.MILLISECONDS)
        .subscribeOn(Schedulers.newThread())
        .subscribe(subject::onNext);

Subscription portraitSub = subject.subscribe(
        s -> System.out.println("Portrait: " + s));

/** onDestroy() */
portraitSub.unsubscribe();

/** Rotating... */
Thread.sleep(300);

/** onRestoreInstanceState() **/
Subscription landscapeSub = subject.subscribe(
        s -> System.out.println("Landscape: " + s));

/** Output */
> Landscape: value
Jimeux
  • 2,956
  • 1
  • 18
  • 14
  • Would be interesting to see how this plays out in an activity context, considering potential memory leaks, necessity to persist subject/observable after the activity destruction, etc. – AndroidEx Nov 06 '15 at 17:40
  • I'm only really experimenting at this stage, but I have a retained fragment with a `WeakHashMap` of presenters. When closing the activity, the subject is unsubscribed, and the presenters are GC'd. However, I don't think the user going back during a request would cancel the request. Some kind of shutdown code in the retained fragment's `onDestroy()` could be part of a solution. – Jimeux Nov 07 '15 at 06:22
0

I have a working example RxApp that uses AsyncSubject to implement cache for network request and the code shows how to subscribe to a pending request. I'm a bit confused with Rx subjects as on the other they seem pretty handy but on the other hand it's recommended that they are to be used only in very seldom cases e.g. To Use Subject Or Not To Use Subject?. Would be great if some one could explain what really is the problem if they're used like in my example.

pmellaaho
  • 792
  • 1
  • 8
  • 15