Edit: Shortly after writing this, I realized that the solution that I present here isn’t very good. I’m leaving it here just in case it can serve as a building block for better solutions.
Sometimes you don’t have control over the lifecycle of your
Subscribers. In these cases, to avoid leaking your
Subscriber, you have to unsubscribe from your
Observable when you’re notified that your
Subscriber is about to be destroyed. It can be really annoying to have to worry about unsubscribing your
Subscriptionsto avoid memory leaks, so in this post, I’ll show how, with a few lines of code, you can stop worrying about leaking your
Before I try to show how to memory-leak-proof your
Subscribers, I want to give a concrete example that shows when memory-leak-proof
Subscribers might be useful. This example will also clarify the problem that memory-leak-proof
Subscribers are trying to solve. I spend most of my time doing Android development these days, so an Android example is the most natural way for me to elaborate on this problem, so here’s an Android-specific use-case: You’d probably want want a memory-leak-proof
Subscriber when you’re writing an
Activity is basically a screen that you see when you’re using an Android app. The Android framework manages the lifecycle of
Activities, moreover, are also often responsible for responding to touch events.
Sometimes you want to fetch some data and then update the UI with that data in response to a touch event, and sometimes fetching data can’t be done on the main thread.
Observables can be a nice way to handle this problem:
However, if the Android framework wants to destroy your
Activity while your
Observable is doing its thing, you run into a problem: The
Observable will keep your Activity from being garbage collected, because your
Activity contains a reference to an anonymous inner
Subscriber and this
Subscriber implicitly contains a reference to your
The straightforward solution to this is to unsubscribe from your
Observable when the
Activity is about to be destroyed:
Although this solution is straightforward, it puts you in an unfortunate dilemma:
- Horn 1: You have to worry about unsubscribing from your
Observerin all of your
Activitiesin your app
- Horn 2: You have to unsubscribe in a base
Activityclass that calls unsubscribe on a
CompositeSubscription, have subclasses add
Subscriptionsto the base
CompositeSubscription, and make all of your
Activitiesextend that base class.¹
I think there might be a better solution: If we subclass
Observable to wrap our
Subscribers in a
Subscriber decorator that delegates work to its weakly held, wrapped
Subscriber, we can keep clients from having to worry about leaking their
Subscribers without forcing them to write boilerplate code.
To see how this would work, let’s start by defining the
Next, we define the Observable subclass that adds a
safeSubscribe() method to wrap the
Subscriber passed in:
And that’s it. Now, clients can subscribe to an
Observable without having to worry about leaking an object with a big memory footprint. Instead, only the
Subscriber decorator is leaked, and since the Subscriber decorator doesn’t have a big memory footprint, its not a huge deal if it sticks around until the
Observer is done doing its thing.
I would love to hear what you all think about this approach.
Edit: Conversation with jackhexen on the Reddit machine has made me realize that this solution is not as clean as I’ve presented it here. Activities won’t maintain strong references to their anonymous inner classes unless you store those classes in an instance variable, so technically, you’d have to store your
Subscribers in instance variables to prevent them for being garbage collected. This makes the solution presented here seem significantly less appealing because I was hoping to offer a solution that kept clients from having to worry about memory management. This solution clearly doesn’t do that.
- This solution is discussed in the 4th part of Dan Lew’s helpful introduction to RxJava for Android.