-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Description
Hi,
I saw a lot of RxJava tutorials (for both 1.x and 2.x versions) on the internet where the Java anonymous inner classes (AIC) are used to construct Observable
chains. Some guides (like this one) advise to use Retrolambda instead, but Retrolamda lambdas are converted to AIC anyway.
Now consider the following example:
public class SomeActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getMyObservable()
.map(new Function<InputType, OutputType>() {
@Override
public OutputType apply(final InputType input) {
...
return someOutput;
}
})
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BiConsumer<ResultType, Throwable>() {
@Override
public void accept(@NonNull ResultType result, @NonNull Throwable throwable) throws Exception {
// Handle result here...
}
});
}
}
Imagine MyObservable
internally starts some long-running async task. As you can see, there are two AIC in the example above which hold implicit references to the enclosing Activity
.
And what would happen on a configuration change:
- A new
Activity
instance is created - The old
Activity
is not needed anymore and, therefore, it must be garbage-collected. But it can't! Since the long-running task is still in progress the oldActivity
instance will be alive because of the implicit references that were passed tomap
andsubscribe
.
This popular tutorial suggests to overcome this issue by unsubscribing in onPause
or some other lifecycle event. But, can you tell me, does unsubscribing really destroy somehow all these implicit references that were passed with AIC?
I've checked RxJava operators source code and, as far as I can see, there is no such functionality there (correct me if I'm wrong). For example, let's take a closer look at ObservableFromCallable:
@Override
public void subscribeActual(Observer<? super T> s) {
DeferredScalarDisposable<T> d = new DeferredScalarDisposable<T>(s);
s.onSubscribe(d);
if (d.isDisposed()) {
return;
}
T value;
try {
value = ObjectHelper.requireNonNull(callable.call(), "Callable returned null");
...
Here callable.call()
may represent a long-running operation. And while this operation is executing the reference to the Observer
s
will be alive so it cannot be garbage-collected, right? Can you explain how exactly unsubscribing will kill the reference to the observer?
It seems that everyone is happy with AIC and Retrolambda and I feel like I'm missing something :)