You don’t have to use WeakReference to avoid memory leaks
One of my colleagues recently mentioned that they saw a presentation that says:
If you are an Android developer and you do not use WeakReferences, you have a problem.
I personally think that, not only that is a wrong argument but it is also totally misleading. WeakReference should be the last resort to fix a memory leak.
Then today, I came across the post in Google Developers Experts publication by Enrique López Mañas
It is very good article that summarize how references work in Java with examples.
The article does not say that we have to use WeakReference but it also does not give any alternative. I felt like I must give alternatives to show that it is not a must to use WeakReference.
You don’t really have any problem if you do not use WeakReference.
I believe that it is not the best practice to use WeakReference in every place you can. Using a WeakReference to fix a memory leak indicates a lack of modeling or architecture.
Although the example given in the article fixes the potential memory leak, there are other ways. I would like to give couple of example implementations to avoid memory leaks when you have a long running background task.
A simple example with AsyncTask to avoid memory leaks would be something like this:
Here is my Activity:
public class MainActivity extends Activity { private MyAsyncTask task; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
task = new MyAsyncTask();
task.setListener(createListener());
task.execute();
} @Override
protected void onDestroy() {
task.setListener(null);
super.onDestroy();
} private MyAsyncTask.Listener createListener() {
return new MyAsyncTask.Listener() { @Override
public void onSuccess(Object object) {
// adapt contents
}
};
}
}
And here is the AsyncTask:
class MyAsyncTask extends AsyncTask { private Listener listener; @Override
protected Object doInBackground(Object[] params) {
return doSomeStuff();
} private Object doSomeStuff() {
//do something to get result
return new Object();
} @Override
protected void onPostExecute(Object object) {
if (listener != null) {
listener.onSuccess(object);
}
} public void setListener(Listener listener) {
this.listener = listener;
} interface Listener {
void onSuccess(Object object);
}
}
This implementation is of course pretty basic but I think it is enough to showcase another solution.
Here is another very simple implementation with RxJava where we still don’t have WeakReference.
public class MainActivity extends Activity {
private Subscription subscription;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
subscription = Observable
.fromCallable(new Callable<Object>() {
@Override
public Object call() throws Exception {
return doSomeStuff();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Object>() {
@Override
public void call(Object o) {
// adapt contents
}
});
}
private Object doSomeStuff() {
//do something to get result
return new Object();
}
@Override
protected void onDestroy() {
subscription.unsubscribe();
super.onDestroy();
}
}
Note that we may still have memory leaks if we don’t unsubscribe from the Subscription.
Lastly I would like to give these example projects from Novoda. They are great resources to learn. As you can guess, they don’t have any WeakReference :)
I believe the rule of thumb (for me) is to make classes static if they are inner classes. Especially if they do long running operation in background. Even better, we can move those classes into a full class of its own.
Using non-static inner classes for long running operations is always a bad practice, not just in Android.