How to unsubscribe from Observable when using Android library
Q Why has my Observable timer never rang? @ Miguel Lavigne says:
"Keep in mind that if you are using Observables from a Fragment or Activity, you should always be sure to unsubscribe your observers to eliminate the possibility of a memory leak."
It is clear to me how this works as long as I use Observable in Activity, Fragment or View. But what if I use it where there is no context?
My situation: I have an external library that contains an object model. Every object has a .save () function that is called from the user interface. In save, the call to the API endpoint is done asynchronously.
Example:
public Overlay save() {
Observable.create(new Observable.OnSubscribe<Overlay>() {
@Override public void call(Subscriber<? super Overlay> subscriber) {
try {
Overlay overlay= OverlayEndpoint.insertOverlay(this); // call the API endpoint here
subscriber.onNext(overlay);
subscriber.onCompleted();
} catch (IOException e) {
subscriber.onError(e);
}
}
}).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Overlay>() {
@Override public void call(Overlay overlay) {
// process the saved result [omitted for brevity]
}
}, new Action1<Throwable>() {
@Override public void call(Throwable throwable) {
// put the overlay into a local upload queue in case the endpoint is unreachable [omitted]
}
});
return this; // return the call immediately
}
Observable is one-time use during save and becomes obsolete thereafter. How can I make sure it is not being saved?
Situation 1: Normal cancellation of a subscription. Is there a way to unsubscribe directly from the call () once processing is complete?
Situation 2: For some reason, the Observable remains in memory. Can I use .timeout () to ensure that the Observable is destroyed after enough time has passed?
source to share
Situation 1: Normal cancellation of a subscription. Is there a way to unsubscribe directly from the call () once processing is complete?
In your case Observable
will be in memory before calling Action1<Overlay>
or new Action1<Throwable>
. But after calling one of them the GC should clean up Observable
.
Situation 2: For some reason, the Observable remains in memory. Can I use .timeout () to ensure that the Observable is destroyed after enough time has passed?
In your case Schedulers.newThread()
will create a new one Thread
to run Observable.OnSubscribe<Overlay>.call
. So if this method has not returned yet, for example OverlayEndpoint.insertOverlay
will run for about 10 minutes, the Observable
GC cannot be flushed because this thread is still using it. There is nothing we can do if there is a cancellation approach OverlayEndpoint.insertOverlay
.
source to share