Activity leak while using volley listeners

前端 未结 1 1763
迷失自我
迷失自我 2021-01-13 07:56

I\'m using volley library for sending requests and I have a memory leak. I traced it with leak canary and it seems to be from my requests mListeners. after some searching I

1条回答
  •  鱼传尺愫
    2021-01-13 08:46

    After some researching I found that the volley listeners cause the activity leak because they are instantiated as anonymous classes and therefore hold an implicit reference to their outer class (in this example news activity) so I made a separate class for VolleyRequest (just to make them customizable not really related to the leak) and made a listener interface which I implement as an innerclass and use a weak reference to have access to the activity

    request code :

    public class MyVolleyStringRequest extends com.android.volley.toolbox.StringRequest {
    
        StringResponseListener mListener;
    
        public MyVolleyStringRequest(int method, String url, final StringResponseListener mListener) {
            super(method, url, new Response.Listener() {
                @Override
                public void onResponse(String s) {
                        mListener.onSuccess(s);
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                        mListener.onFailure(volleyError);
                }
            });
            this.mListener = mListener;
        }
    
        @Override
        public Map getHeaders() throws AuthFailureError {
            Map params = new HashMap<>();
            Log.e("sent token", "Token " + G.token);
            params.put("Authorization", "Token " + G.token);
            params.put("Accept-Language", "en-US,en;q=0.8,fa;q=0.6,pt;q=0.4,ar;q=0.2,gl;q=0.2");
    
            return params;
        }
    
        @Override
        protected Response parseNetworkResponse(NetworkResponse response) {
            try {
                String utf8String = new String(response.data, "UTF-8");
                return Response.success(utf8String, HttpHeaderParser.parseCacheHeaders(response));
            } catch (UnsupportedEncodingException e) {
                return Response.error(new ParseError(e));
            }
    
        }
    
    
    }
    

    requestLike and requestView Code:

    private void requestLike(final ImageButton likeButton, final long id) {
    
                MyVolleyStringRequest likeRequest = new MyVolleyStringRequest(Request.Method.POST, G.likeURL + id + "/like",
                        new RequestLikeStringListener(this));
                MyVolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(likeRequest, "like");
        }
    
        private void requestView(long id) {
            MyVolleyStringRequest viewRequest = new MyVolleyStringRequest(Request.Method.GET, G.viewURL + id + "/view",
                    new RequestViewStringListener());
            MyVolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(viewRequest, "view");
        }
    

    listener interface code :

    public interface StringResponseListener {
        void onSuccess(String response);
        void onFailure(VolleyError error);
    }
    

    innerclasses code:

    public static class RequestLikeStringListener implements StringResponseListener{
    
            WeakReference contextWeakReference;
            RequestLikeStringListener(NewsActivity context){
                contextWeakReference = new WeakReference<>(context);
    
            }
    
            public void onSuccess(String response) {
                try {
                    NewsActivity context = contextWeakReference.get();
                    if(context != null) {
                        ImageButton likeButton = (ImageButton) context.findViewById(R.id.likeButton);
                        Log.e("requestLikeJson", response);
                        JSONObject likeObject = new JSONObject(response);
                        int likeNumbers = likeObject.getInt("likes");
    
                        if (likeButton.getTag().equals("notliked")) {
                            context.setLikeChangeInDatabase(false, contextWeakReference.get().id, likeNumbers);
                        } else {
                            context.setLikeChangeInDatabase(true, contextWeakReference.get().id, likeNumbers);
                        }
                    }
    
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
    
            public void onFailure(VolleyError error) {
                NewsActivity context = contextWeakReference.get();
                if(context != null) {
                    ImageButton likeButton = (ImageButton) context.findViewById(R.id.likeButton);
                    Toast.makeText(context, "No Internet connection", Toast.LENGTH_LONG).show();
                    try {
                        error.printStackTrace();
                        Log.e("network error", new String(error.networkResponse.data));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    if (likeButton.getTag().equals("notliked")) {
                        likeButton.setTag("liked");
                        context.likeButtonImageSetter();
                    } else {
                        likeButton.setTag("notliked");
                        context.likeButtonImageSetter();
                    }
                    Animation shake = AnimationUtils.loadAnimation(context, R.anim.actionfeedback);
                    likeButton.startAnimation(shake);
                }
            }
    

    hope it helps someone!

    0 讨论(0)
提交回复
热议问题