After reading this article, I started thinking about memory leaks with Volley. Usually, the listeners implemented with Volley have either an implicit or explicit reference to the outer class (the activity). for example:
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
url, null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
updateLayout();
}
}
in this case there is an implicit reference... or I may want to create a custom JsonObjectRequest to internalize the response handling, and need to pass in a reference to the calling activity in its constructor.
Now lets say I start a web request, but before the response comes back, I navigate away from the activity that started the request. From what I understand the JsonObjectRequest object would keep a reference to my activity and prevent it from being Garbage collected.
-Am I understanding this correctly, is this a legitimate fear?
-Does the Volley library automatically deal with this?
-If am creating a custom JsonObjectRequest and passing in a "this" (reference to activity), do I need to create a WeakReference to the activity?
I hava faced memory leak when using volley just like the way you write here.everytime I new a new listener.
I used leakcanary to detect leaking.
When I read about your article, http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html ,and used WeakReference to activity and callback interface(myself customed), it solved.
I used volley as a singleton.
I also read this answer,How to use WeakReference in Java and Android development? ,the second answer give an example just like your article provide.It's good.
Based on looking at the volley code, calling cancel doesn't really avoid the memory leak because the reference never gets cleared and the reference isn't weak. Calling cancel only avoids Volley from delivering the response to the listener.
My solution to the problem would have to be cloning and modifying the library myself.
One of the solutions can be to make base ErrorListener reference inside of base Request.java to be weak reference. And similarly the same can be done to the Listener inside of JsonRequest.java.
The other solution can be to manually clear the reference upon cancel being called. inside of cancel(), set the mErrorListener and mListener to null. With this solution though, you'll have to remove the final modifier from the field declaration otherwise you wouldn't be allowed to set the reference to null.
Hope this helps.
I am probably late to this party by a year but I just figured a way to solve this issue. Here it is:
here you can use activityWeakReference.get() to access all the UI elements of the MainActivity too. Found this from http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html. This way we don't need to cancel any requests in onStop(). Remember to use
activityWeakReference.get().isFinishing
&&activityWeakReference.get()!=null
to avoid crashes when the activity does not exist.