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?
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 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.
public interface VolleyCallback {
void onSuccess(JSONObject result);
void onFailed(String error);
}
private static class SListener implements Response.Listener<JSONObject> {
private final WeakReference<Activity> activityWeakReference;
private final WeakReference<VolleyCallback> callbackWeakReference;
public SListener(Activity activity, VolleyCallback callback) {
activityWeakReference = new WeakReference<Activity>(activity);
callbackWeakReference = new WeakReference<VolleyCallback>(callback);
}
@Override
public void onResponse(JSONObject jsonObject) {
Activity act = activityWeakReference.get();
VolleyCallback vc = callbackWeakReference.get();
if (act != null && vc != null) {
LogUtil.d(TAG, act.toString() + " " + jsonObject.toString());
something you need to do;
vc.onSuccess(jsonObject);
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With