When to dispose RxJava2 Disposable in ViewModel?
Asked Answered
A

2

17

I'm using ViewModel from Android Architecture Components in my app. In the ViewModel, I'm using RxJava2 subscription and I keep Disposable object after I subscribe. Before, when I did this in Activity, I was used to dispose the Disposable in onDestroy() - to avoid memory leaks:

@Override
protected void onDestroy() {
    disposable.dispose();
    super.onDestroy();
}

When and how should I dispose it in ViewModel? Do I actually need to do that?

Anastomose answered 1/4, 2018 at 19:14 Comment(0)
S
26

with onCleared method

@Override
protected void onCleared () {
    disposable.dispose();
    super.onCleared ();
}
Savage answered 1/4, 2018 at 19:18 Comment(4)
This method called only when activity pop from back stack. This lead data stream not disposed when you open second activity and first activity pushed to back stack.Interpol
@Sergey You activity may be destroy at any time when it gets on background anyway while your activity is not destroyed in most case you certainly doesn't want to kill your data streams otherwise if activity came back foregroung before being destroyed all your streams would be killed and thus you activity will be desynchronized from you datasSavage
I found that I have to clear disposables in 2 places: 1) in oncleared as above, as well as 2) in ondestroyview method of my fragments. >> If I don't clear disposables as per 1), then my subscriber is triggered when context is null after leaving view and app crashes. If I dont clear as per 2), then I get memory leak issues, which for example caused intermittency on my click listeners after back navigation.Cruck
@RowanGontier i never used rx on controller side (fragments), i use rx only from viewmodel and livedata on controller side, LiveDataReactiveStreams#fromPublisher can be helpful converting rx to livedata. That way you don't need to dispose on controller sideSavage
H
3

You could use LiveDataReactiveStreams#fromPublisher(Publisher<T>) and expose resulting LiveData from the view model, instead of subscribing and disposing in the view model.

For example:

public class ExampleViewModel {

    private static final long TIME_FOR_ANSWER = 1000;
    private static final long DELAY = 25;

    private final LiveData<Long> remainingTime;

    ExampleViewModel() {
        long start = 0;
        long count = TIME_FOR_ANSWER / DELAY + 1;
        Flowable<Long> flowable =
              Flowable.intervalRange(start, count, 0, DELAY, TimeUnit.MILLISECONDS)
                      .map(i -> TIME_FOR_ANSWER - DELAY * i);
        remainingTime = LiveDataReactiveStreams.fromPublisher(flowable);
    }

    public LiveData<Long> getRemainingTime() {
        return remainingTime;
    }
}
Horvitz answered 4/4, 2018 at 6:10 Comment(4)
What I'm actually doing is I use Observable.timer here. Could you advise me how to use it with LiveDataReactiveStreams? Here's the code: gist.github.com/micer/93b02625bd078e52c5258eabaaea4449Anastomose
Also, here's how to handle rotation: https://mcmap.net/q/535117/-resume-flowable-converted-to-live-data-after-screen-rotation/1916449Horvitz
hey, when we use LiveDataReactiveStreams it handles Rx Observation the way CompositDisposable does?Nephrotomy
@yasin Not sure what you mean by that, maybe you can post that as a separate question and elaborate a little bit?Horvitz

© 2022 - 2024 — McMap. All rights reserved.