2016-07-25 7 views
4

Etwas Schlimmes passiert, wenn Volley mit einer großen Antwort zu behandeln:Android, Volley Anfrage, die Antwort blockiert Hauptthread

String url = AppHelper.DOMAIN + "/service/pages/profile_update.json"; 

this.infoTextView.setText(getString(R.string.profile_info_updating)); 

final StringRequest stringRequest = new StringRequest(Request.Method.POST, url, 
     new Response.Listener<String>() { 
      @Override 
      public void onResponse(String response) { 
       try { 
        JSONObject json = new JSONObject(response); 

        if (json.getBoolean("success")) { 
         // manage JSON object here 
        } else { 
         Toast.makeText(ProfileActivity.this, 
           getString(R.string.connection_problem_server), 
           Toast.LENGTH_LONG).show(); 
        } 
       } catch (JSONException e) { 
        ProfileActivity.this.infoTextView.setText(
          getString(R.string.profile_info_updating_error)); 

        e.printStackTrace(); 
       } 
      } 
     }, new Response.ErrorListener() { 
    @Override 
    public void onErrorResponse(VolleyError error) { 
     ProfileActivity.this.infoTextView.setText(
       getString(R.string.profile_info_updating_error)); 

     if (error.networkResponse != null && error.networkResponse.statusCode == 401) { 
      Toast.makeText(ProfileActivity.this, 
        getString(R.string.connection_problem_permission), 
        Toast.LENGTH_LONG).show(); 
     } 

     new android.os.Handler().postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       if (ProfileActivity.this.swipeRefreshLayout != null) { 
        ProfileActivity.this.swipeRefreshLayout.setRefreshing(false); 
       } 
      } 
     }, 1000); 

     error.printStackTrace(); 
    } 
}) { 
    @Override 
    protected Map<String, String> getParams() { 
     Map<String, String> params = new HashMap<>(); 
     params.put("auth_token", ProfileActivity.this.defaultUser.getAuthenticationToken()); 
     return params; 
    } 

    @Override 
    public Map<String, String> getHeaders() throws AuthFailureError { 
     Map<String, String> params = new HashMap<>(); 
     params.putAll(super.getHeaders()); 
     params.put("Accept-Encoding", "gzip,deflate"); 
     return params; 
    } 

    @Override 
    protected Response<String> parseNetworkResponse(NetworkResponse response) { 
     StringBuilder output = new StringBuilder(); 
     try { 
      GZIPInputStream gStream = new GZIPInputStream(new ByteArrayInputStream(response.data)); 
      InputStreamReader reader = new InputStreamReader(gStream); 
      BufferedReader in = new BufferedReader(reader, 16384); 

      String read; 

      while ((read = in.readLine()) != null) { 
       output.append(read).append("\n"); 
      } 
      reader.close(); 
      in.close(); 
      gStream.close(); 
     } catch (IOException error) { 
      error.printStackTrace(); 
      return Response.error(new ParseError()); 
     } 

     return Response.success(output.toString(), HttpHeaderParser.parseCacheHeaders(response)); 
    } 
}; 

stringRequest.setRetryPolicy(new RetryPolicy() { 
    @Override 
    public int getCurrentTimeout() { 
     // 40 seconds 
     return 40000; 
    } 

    @Override 
    public int getCurrentRetryCount() { 
     return DefaultRetryPolicy.DEFAULT_MAX_RETRIES; 
    } 

    @Override 
    public void retry(VolleyError error) throws VolleyError { 
     throw error; 
    } 
}); 

Volley.newRequestQueue(this).add(stringRequest); 

dieser Codeblock des Haupt-Thread, um die Anwendung einfriert.

Zusätzlich habe ich einige Header-Werte gesetzt, um gzip-Antwort und einen Code zu ermöglichen, mit den Daten umzugehen. Aber es ist nicht das Stück, das unerwünschtes Verhalten hervorruft. Die Anwendung wird erst eingefroren, wenn onResponse(String response) gestartet wird.

Was kann ich tun, um dies zu vermeiden?

+1

Es hat wahrscheinlich mit der Tatsache zu tun, dass Sie die JSON tun auf dem UI-Thread-Parsing, statt in 'parseNetworkResponse' – EpicPandaForce

+0

-Code scheint zu sein, gut .. könnten Sie anderen Teil des Codes um diese Netzwerkanforderung verfügbar machen? – Dexto

Antwort

9

onResponse und onErrorResponse wird auf UI-Thread aufgerufen, daher wird jede schwere Operation innerhalb dieser Methoden Ihre Anwendung weniger reaktionsfähig machen. Ich schätze, Sie versuchen, die Antwort in onResponse() zu analysieren, die falsch ist.

Sie haben seit dieser zu Parsen Logik parseNetworkResponse zu bewegen, ist die Methode, die im Hintergrund-Thread aufgerufen wird. Siehe den Link unten für weitere Informationen:

https://developer.android.com/training/volley/request-custom.html

+1

danke für deine antwort! – zerokol

+0

Was ist, wenn die Aufrufanforderung von 'IntentService' gemacht wurde, wird' onResponse() 'dann im UI-Thread ausgeführt? –

+0

Doest egal, was der aufrufende Thread ist. onResponse() wird im UI-Thread aufgerufen. –