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?

Micer
  • 8,731
  • 3
  • 79
  • 73

2 Answers2

26

with onCleared method

@Override
protected void onCleared () {
    disposable.dispose();
    super.onCleared ();
}
Samuel Eminet
  • 4,647
  • 2
  • 18
  • 32
  • 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. – Sergei Bubenshchikov Sep 21 '18 at 09:10
  • 1
    @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 datas – Samuel Eminet Sep 21 '18 at 10:00
  • 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. – Rowan Gontier Mar 05 '20 at 23:48
  • 1
    @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 side – Samuel Eminet Mar 06 '20 at 13:30
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;
    }
}
arekolek
  • 9,128
  • 3
  • 58
  • 79
  • 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: https://gist.github.com/micer/93b02625bd078e52c5258eabaaea4449 – Micer Apr 04 '18 at 11:19
  • Also, here's how to handle rotation: https://stackoverflow.com/q/47382786/1916449 – arekolek Apr 04 '18 at 15:48
  • hey, when we use LiveDataReactiveStreams it handles Rx Observation the way CompositDisposable does? – Yasin Hajilou Jun 19 '20 at 06:40
  • @yasin Not sure what you mean by that, maybe you can post that as a separate question and elaborate a little bit? – arekolek Jun 20 '20 at 10:20