2015-08-30 7 views
5

Uso la libreria di volley per inviare richieste e ho una perdita di memoria. L'ho rintracciato con canary leak e sembra provenire dalle mie richieste mListeners. Dopo qualche ricerca ho annullare tutte le mie richieste nella mia attività in corso, ma ancora ho una perdita potrei usare un certo aiuto grazie ecco il mio codice per il download: (nota: io uso pattern Singleton per ottenere richiesta volley coda)Perdita di attività durante l'utilizzo degli ascoltatori di pallavolo

private void startImageDownloadService(final NEWS selectedNews) { 
     if (selectedNews.getIMG_URL() != null && !selectedNews.getIMG_URL().equals("null")) { 
      ImageRequest imageRequest = new ImageRequest(selectedNews.getIMG_URL(), 
        new Response.Listener<Bitmap>() { 
       @Override 
       public void onResponse(Bitmap bitmap) { 
        newsImage_imageView.setVisibility(View.VISIBLE); 
        newsImage_imageView.setImageBitmap(bitmap); 
        saveImageToFileStarter(bitmap, selectedNews); 
       } 
      }, 200, 200, null, null, new Response.ErrorListener() { 
       @Override 
       public void onErrorResponse(VolleyError volleyError) { 
        Toast.makeText(getApplicationContext(), "Failed to download image", Toast.LENGTH_SHORT).show(); 
       } 
      }); 
      imageRequest.setShouldCache(false); 
      MyVolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(imageRequest, "newsActivityImage"); 
// 
     } 
    } 


private void requestLike(final ImageButton likeButton, final long id) { 
     try { 
      StringRequest jsonRequest = new StringRequest(Request.Method.POST, G.likeURL + id + "/like", 
        new Response.Listener<String>() { 
       @Override 
       public void onResponse(String s) { 
        try { 
         Log.e("requestLikeJson", s); 
         JSONObject likeObject = new JSONObject(s); 
         int likeNumbers = likeObject.getInt("likes"); 
//      Toast.makeText(NewsActivity.this, likeNumbers + "", Toast.LENGTH_LONG) 
//        .show(); 
         if (likeButton.getTag().equals("notliked")) { 
          setLikeChangeInDatabase(false, id, likeNumbers); 
         } 
         else{ 
          setLikeChangeInDatabase(true, id, likeNumbers); 
         } 
//      viewsCount_textView.setText("" + likeNumbers); 
        } catch (JSONException e) { 
         e.printStackTrace(); 
        } 
       } 
      }, new Response.ErrorListener() { 
       @Override 
       public void onErrorResponse(VolleyError volleyError) { 
        Toast.makeText(NewsActivity.this, "No Internet connection", Toast.LENGTH_LONG).show(); 
        try { 
         volleyError.printStackTrace(); 
         Log.e("network error", new String(volleyError.networkResponse.data)); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
        if (likeButton.getTag().equals("notliked")) { 
         likeButton.setTag("liked"); 
         likeButtonImageSetter(); 
        } else { 
         likeButton.setTag("notliked"); 
         likeButtonImageSetter(); 
        } 
        Animation shake = AnimationUtils.loadAnimation(NewsActivity.this, R.anim.actionfeedback); 
        likeButton.startAnimation(shake); 
       } 
      }) { 

       @Override 
       public Priority getPriority() { 
        return Priority.HIGH; 
       } 

       @Override 
       public Map<String, String> getHeaders() throws AuthFailureError { 
        Map<String, String> 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<String> parseNetworkResponse(NetworkResponse response) { 
        String utf8String = null; 
        try { 
         utf8String = new String(response.data, "UTF-8"); 
         return Response.success(utf8String, HttpHeaderParser.parseCacheHeaders(response)); 

        } catch (UnsupportedEncodingException e) { 
         return Response.error(new ParseError(e)); 
        } 

       } 
      }; 
      jsonRequest.setRetryPolicy(new DefaultRetryPolicy(
        G.socketTimeout, 
        0, 
        DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); 

      MyVolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonRequest, "like"); 
     } catch (Exception e) { 

     } 
    } 

    private void requestView(long id) { 

     try { 
      StringRequest jsonRequest = new StringRequest(Request.Method.GET, G.viewURL + id + "/view", new Response.Listener<String>() { 
       @Override 
       public void onResponse(String s) { 
        try { 
         JSONObject viewObject = new JSONObject(s); 
         Log.e("requestViewJson", s); 

        } catch (JSONException e) { 
         e.printStackTrace(); 

        } 
       } 
      }, new Response.ErrorListener() { 
       @Override 
       public void onErrorResponse(VolleyError volleyError) { 
        try { 
         volleyError.printStackTrace(); 
         Log.e("network error", new String(volleyError.networkResponse.data)); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 
      }) { 

       @Override 
       public Map<String, String> getHeaders() throws AuthFailureError { 
        Map<String, String> 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 
       public Priority getPriority() { 
        return Priority.HIGH; 
       } 

       @Override 
       protected Response<String> parseNetworkResponse(NetworkResponse response) { 
        String utf8String = null; 
        try { 
         utf8String = new String(response.data, "UTF-8"); 
         return Response.success(utf8String, HttpHeaderParser.parseCacheHeaders(response)); 

        } catch (UnsupportedEncodingException e) { 
         return Response.error(new ParseError(e)); 
        } 

       } 
      }; 
      jsonRequest.setRetryPolicy(new DefaultRetryPolicy(
        G.socketTimeout, 
        0, 
        DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); 

      MyVolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonRequest,"view"); 
     } catch (Exception e) { 

     } 
    } 

e nel mio onStop() ho:

@Override 
    protected void onStop() { 
     try {//new change 
      MyVolleySingleton.getInstance(getApplicationContext()).cancelPendingRequests("newsActivityImage"); 
      MyVolleySingleton.getInstance(getApplicationContext()).cancelPendingRequests("view"); 
      MyVolleySingleton.getInstance(getApplicationContext()).cancelPendingRequests("like"); 
      loadImageFromFile.cancel(true); 
      loadImageFromFile=null; 
      }catch (Exception e){} 
     super.onStop(); 

    } 
+0

fare riferimento a questo link: http://stackoverflow.com/a/43723971/5860087 Questo potrebbe risolvere il vostro scopo. Ciao –

risposta

3

Dopo qualche ricerca ho scoperto che gli ascoltatori volley causano la perdita di attività, perché sono istanziati come classi anonime e, pertanto, in possesso di un implicito riferimento alla loro classe esterna (in questo esempio attività di notizie) quindi ho creato una classe separata per VolleyRequest (solo per renderli personalizzabili non proprio legati alla perdita) e realizzato un'interfaccia ascoltatore che implemento come classe interna e utilizzare un riferimento debole per avere accesso alle attività

codice

richiesta:

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<String>() { 
      @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<String, String> getHeaders() throws AuthFailureError { 
     Map<String, String> 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<String> 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 e requestView Codice:

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"); 
    } 

codice di interfaccia ascoltatore:

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

i codice nnerclasses:

public static class RequestLikeStringListener implements StringResponseListener{ 

     WeakReference<NewsActivity> 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); 
      } 
     } 

spero che aiuti qualcuno!