I use google's volley library and I have been battling memory leaks in my apps for weaks now. I have done soo much research and tried soo much already but now I just do not know what to do. This is a sample code:
SplashActivity.java
public class SplashActivity extends AppCompatActivity {
Context mContext;
AuthRequest mAuthRequest;
GetTokenOnSuccessListener mGetTokenOnSuccessListener;
GetTokenOnErrorListener mGetTokenOnErrorListener;
private ConfigTable mConfigTable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initialiseViewsAndComponents();
}
@Override
protected void onStart() {
super.onStart();
getAuthToken();
}
private void initialiseViewsAndComponents() {
mContext = SplashActivity.this;
mAuthRequest = new AuthRequest(mContext);
mGetTokenOnSuccessListener = new GetTokenOnSuccessListener(mContext);
mGetTokenOnErrorListener = new GetTokenOnErrorListener(mContext);
mConfigTable = new ConfigTable(mContext);
}
private void getAuthToken() {
if (!mConfigTable.get("INITIALISED").equals("")) {
mAuthRequest.guest(mGetTokenOnSuccessListener, mGetTokenOnErrorListener);
} else {
Intent mainIntent = new Intent(mContext, MainActivity.class);
startActivity(mainIntent);
}
}
}
GetTokenOnSuccessListener.java
public class GetTokenOnSuccessListener implements Response.Listener<JSONObject> {
//private Activity mActivity;
private Context mContext;
private ConfigTable mConfigTable;
private int mSuccess = 0;
private String mMessage = "";
public GetTokenOnSuccessListener(Context context) {
//this.mActivity = context;
this.mContext = context;
this.mConfigTable = new ConfigTable(this.mContext);
}
@Override
public void onResponse(JSONObject response) {
try {
mSuccess = Integer.parseInt(response.get("success").toString());
mMessage = response.get("message").toString();
if (mSuccess == 1) {
mConfigTable.setAuthToken(response.get("message").toString());
Intent mainIntent = new Intent(mContext, MainActivity.class);
mContext.startActivity(mainIntent);
((SplashActivity) mContext).finish();
} else {
Toast.makeText(mContext, "Lol access denied, could not retrieve token from server.", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(mContext, "Lol access denied, could not retrieve token from server.", Toast.LENGTH_SHORT).show();
}
}
}
GetTokenOnErrorListener.java
public class GetTokenOnErrorListener implements Response.ErrorListener {
private Context mContext;
public GetTokenOnErrorListener(Context context) {
this.mContext = context;
}
@Override
public void onErrorResponse(VolleyError error) {
Utils.showNetworkResponse(mContext, error);
}
}
Okay now I moved the response listeners to their own separate classes based on something I read online thinking it will resolve the leak but no it did not. I added code to cancel all pending requests onDestroy() based on the request's tag but still I had memory leaks.
This is just my splash activity and the leaks here are small, I have a feeling it's because I call finish() but I don't get that because I call it after the request has been completed successfully. All my other activities have similar codes but leak more memory as much as 11mb.
So my question is has anyone worked with the volley library? How do I use it and avoid memory leaks?
Using this version:
compile 'com.android.volley:volley:1.0.0'
It's not enough just to "Move response listeners to their own separate classes".
Your listeners have strong references to the Activity (mContext
), introducing a leak during the request. It means that your Activity can't be garbage collected, while the request is ongoing.
It's not really a Volley's fault, but rather a natural way of things.
You have couple of options in your case:
1) Pass a WeakReference<Context>
to your listeners, instead a strong reference to Context. This way you won't introduce a leak and will have to check if this referenced Context isn't yet null, when you try to access it. But I'd rather go for the 2nd option.
2) Set mContext
to null
in listeners, when Activity's onDestroy()
is called. And perform null check as well, when you are trying to do something with Context in listener. So as soon as Activity will be destroyed, you'll remove other strong references to it, allowing GC to collect it normally.
Please update to latest volley version they have fixed memory leaks. 'com.android.volley:volley:1.1.0-rc1'
https://github.com/google/volley/releases/tag/1.1.0-rc1
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