2014-05-06 20 views
12

Tôi đang sử dụng Volley để thực hiện yêu cầu POST trong đơn đăng ký của mình và trong trường hợp của tôi, phản hồi tốt là 201 với thân trống. Tôi đang sử dụng JSONRequest để thực hiện cuộc gọi.Xử lý phản hồi trống trong JSONRequest bằng Volley

Vấn đề của tôi là trình xử lý đáp ứng lỗi đang được gọi vì phản hồi trống.

Dưới đây là yêu cầu của tôi:

Request request = new JsonRequest<Object>(Request.Method.POST, url, body, new Response.Listener<Object>() { 

     @Override 
     public void onResponse(Object response) { 

     } 
    }, new ErrorListener(context)) { 

     @Override 
     protected Response<Object> parseNetworkResponse(NetworkResponse response) { 

      Log.d(TAG, "success!!!!!!"); 
      if (response.statusCode == 201) 
       mListener.resetPasswordWasSent(); 
      return null; 
     } 

     @Override 
     public Map<String, String> getHeaders() throws AuthFailureError { 
      Map<String,String> params = new HashMap<String, String>(); 
      params.put("Content-Type","application/json"); 
      params.put("Accept", "application/json"); 
      return params; 
     } 
    }; 

    requestQueue.add(request); 

chức năng My parseNetworkResponse là nhận được gọi, thì ErrorListener, và phương pháp onResponse không bao giờ bị hit bởi vì tôi nhận được một NullPointerException trong ErrorListener.

Tôi có thể bỏ qua NullPointerException trong trình nghe lỗi của mình, nhưng tôi không muốn. Rõ ràng, tôi chỉ đơn giản có thể gửi gọi lại của tôi trong parseNetworkResponse, nhưng tôi không muốn có bất kỳ lỗi nào xuất hiện.

Bất cứ ai cũng biết cách xử lý vấn đề này?

Edit: Đây là stacktrace:

05-06 09:44:19.586 27546-27560/com.threepoundhealth.euco E/Volley﹕ [1830] NetworkDispatcher.run: Unhandled exception java.lang.NullPointerException 
    java.lang.NullPointerException 
    at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:126) 
+0

đâu Chính xác những gì bạn nhận được 'NullPointerException'? Bên trong Lib hoặc trong mã của bạn? vui lòng thêm StackTrace. – Simulant

+0

@Simulant xin vui lòng xem các chỉnh sửa – coder

+0

Tôi có vấn đề này quá, onError của tôi không bao giờ được gọi là – CQM

Trả lời

7

Bạn có thể sử dụng một StringRequest. Trình nghe của bạn sẽ được gọi với một Chuỗi rỗng "".

+0

Tôi muốn có thể gửi JSON, và không sử dụng phương thức 'getParams' nơi tôi phải tạo bản đồ các tham số – coder

+0

Sử dụng JsonRequest và JsonBodyRequest xuất hiện để đưa ra một lỗi trên một phản hồi trống.Tôi muốn tưởng tượng thats một lỗi nhưng nó có vẻ như StringRequest chỉ là cách để xử lý một phản ứng có sản phẩm nào mà không gây ra errorListener. –

7

Bạn có thể thử hack như thế này. Tạo một lớp con JsonObjectRequest, ghi đè phương thức parseNetworkResponse và kiểm tra dữ liệu phản hồi, nếu nó là rỗng byte[], thay thế dữ liệu bằng byte[] đại diện của một json trống {}.

public class VolleyJsonRequest extends JsonObjectRequest { 

    ... 

    @Override 
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) { 
     try { 
      if (response.data.length == 0) { 
       byte[] responseData = "{}".getBytes("UTF8"); 
       response = new NetworkResponse(response.statusCode, responseData, response.headers, response.notModified); 
      } 
     } catch (UnsupportedEncodingException e) { 
      e.printStackTrace(); 
     } 
     return super.parseNetworkResponse(response); 
    }  
} 
0

Tôi gặp vấn đề tương tự và phát triển giải pháp toàn cầu để xử lý (và thiếu chức năng của Volley), tôi đăng nó lên một chủ đề khác nhưng tôi nghĩ nó có thể giúp nhiều người đang tìm kiếm giải pháp cho vấn đề của bạn.

/** 
    * Created by laurentmeyer on 25/07/15. 
    */ 
public class GenericRequest<T> extends JsonRequest<T> { 

    private final Gson gson = new Gson(); 
    private final Class<T> clazz; 
    private final Map<String, String> headers; 
    // Used for request which do not return anything from the server 
    private boolean muteRequest = false; 

    /** 
     * Basically, this is the constructor which is called by the others. 
     * It allows you to send an object of type A to the server and expect a JSON representing a object of type B. 
     * The problem with the #JsonObjectRequest is that you expect a JSON at the end. 
     * We can do better than that, we can directly receive our POJO. 
     * That's what this class does. 
     * 
     * @param method:  HTTP Method 
     * @param classtype:  Classtype to parse the JSON coming from the server 
     * @param url:   url to be called 
     * @param requestBody: The body being sent 
     * @param listener:  Listener of the request 
     * @param errorListener: Error handler of the request 
     * @param headers:  Added headers 
     */ 
    private GenericRequest(int method, Class<T> classtype, String url, String requestBody, 
          Response.Listener<T> listener, Response.ErrorListener errorListener, Map<String, String> headers) { 
     super(method, url, requestBody, listener, 
       errorListener); 
     clazz = classtype; 
     this.headers = headers; 
     configureRequest(); 
    } 

    /** 
     * Method to be called if you want to send some objects to your server via body in JSON of the request (with headers and not muted) 
     * 
     * @param method:  HTTP Method 
     * @param url:   URL to be called 
     * @param classtype:  Classtype to parse the JSON returned from the server 
     * @param toBeSent:  Object which will be transformed in JSON via Gson and sent to the server 
     * @param listener:  Listener of the request 
     * @param errorListener: Error handler of the request 
     * @param headers:  Added headers 
     */ 
    public GenericRequest(int method, String url, Class<T> classtype, Object toBeSent, 
          Response.Listener<T> listener, Response.ErrorListener errorListener, Map<String, String> headers) { 
     this(method, classtype, url, new Gson().toJson(toBeSent), listener, 
       errorListener, headers); 
    } 

    /** 
     * Method to be called if you want to send some objects to your server via body in JSON of the request (without header and not muted) 
     * 
     * @param method:  HTTP Method 
     * @param url:   URL to be called 
     * @param classtype:  Classtype to parse the JSON returned from the server 
     * @param toBeSent:  Object which will be transformed in JSON via Gson and sent to the server 
     * @param listener:  Listener of the request 
     * @param errorListener: Error handler of the request 
     */ 
    public GenericRequest(int method, String url, Class<T> classtype, Object toBeSent, 
          Response.Listener<T> listener, Response.ErrorListener errorListener) { 
     this(method, classtype, url, new Gson().toJson(toBeSent), listener, 
       errorListener, new HashMap<String, String>()); 
    } 

    /** 
     * Method to be called if you want to send something to the server but not with a JSON, just with a defined String (without header and not muted) 
     * 
     * @param method:  HTTP Method 
     * @param url:   URL to be called 
     * @param classtype:  Classtype to parse the JSON returned from the server 
     * @param requestBody: String to be sent to the server 
     * @param listener:  Listener of the request 
     * @param errorListener: Error handler of the request 
     */ 
    public GenericRequest(int method, String url, Class<T> classtype, String requestBody, 
          Response.Listener<T> listener, Response.ErrorListener errorListener) { 
     this(method, classtype, url, requestBody, listener, 
       errorListener, new HashMap<String, String>()); 
    } 

    /** 
     * Method to be called if you want to GET something from the server and receive the POJO directly after the call (no JSON). (Without header) 
     * 
     * @param url:   URL to be called 
     * @param classtype:  Classtype to parse the JSON returned from the server 
     * @param listener:  Listener of the request 
     * @param errorListener: Error handler of the request 
     */ 
    public GenericRequest(String url, Class<T> classtype, Response.Listener<T> listener, Response.ErrorListener errorListener) { 
     this(Request.Method.GET, url, classtype, "", listener, errorListener); 
    } 

    /** 
     * Method to be called if you want to GET something from the server and receive the POJO directly after the call (no JSON). (With headers) 
     * 
     * @param url:   URL to be called 
     * @param classtype:  Classtype to parse the JSON returned from the server 
     * @param listener:  Listener of the request 
     * @param errorListener: Error handler of the request 
     * @param headers:  Added headers 
     */ 
    public GenericRequest(String url, Class<T> classtype, Response.Listener<T> listener, Response.ErrorListener errorListener, Map<String, String> headers) { 
     this(Request.Method.GET, classtype, url, "", listener, errorListener, headers); 
    } 

    /** 
     * Method to be called if you want to send some objects to your server via body in JSON of the request (with headers and muted) 
     * 
     * @param method:  HTTP Method 
     * @param url:   URL to be called 
     * @param classtype:  Classtype to parse the JSON returned from the server 
     * @param toBeSent:  Object which will be transformed in JSON via Gson and sent to the server 
     * @param listener:  Listener of the request 
     * @param errorListener: Error handler of the request 
     * @param headers:  Added headers 
     * @param mute:   Muted (put it to true, to make sense) 
     */ 
    public GenericRequest(int method, String url, Class<T> classtype, Object toBeSent, 
          Response.Listener<T> listener, Response.ErrorListener errorListener, Map<String, String> headers, boolean mute) { 
     this(method, classtype, url, new Gson().toJson(toBeSent), listener, 
       errorListener, headers); 
     this.muteRequest = mute; 
    } 

    /** 
     * Method to be called if you want to send some objects to your server via body in JSON of the request (without header and muted) 
     * 
     * @param method:  HTTP Method 
     * @param url:   URL to be called 
     * @param classtype:  Classtype to parse the JSON returned from the server 
     * @param toBeSent:  Object which will be transformed in JSON via Gson and sent to the server 
     * @param listener:  Listener of the request 
     * @param errorListener: Error handler of the request 
     * @param mute:   Muted (put it to true, to make sense) 
     */ 
    public GenericRequest(int method, String url, Class<T> classtype, Object toBeSent, 
          Response.Listener<T> listener, Response.ErrorListener errorListener, boolean mute) { 
     this(method, classtype, url, new Gson().toJson(toBeSent), listener, 
       errorListener, new HashMap<String, String>()); 
     this.muteRequest = mute; 

    } 

    /** 
     * Method to be called if you want to send something to the server but not with a JSON, just with a defined String (without header and not muted) 
     * 
     * @param method:  HTTP Method 
     * @param url:   URL to be called 
     * @param classtype:  Classtype to parse the JSON returned from the server 
     * @param requestBody: String to be sent to the server 
     * @param listener:  Listener of the request 
     * @param errorListener: Error handler of the request 
     * @param mute:   Muted (put it to true, to make sense) 
     */ 
    public GenericRequest(int method, String url, Class<T> classtype, String requestBody, 
          Response.Listener<T> listener, Response.ErrorListener errorListener, boolean mute) { 
     this(method, classtype, url, requestBody, listener, 
       errorListener, new HashMap<String, String>()); 
     this.muteRequest = mute; 

    } 


    @Override 
    protected Response<T> parseNetworkResponse(NetworkResponse response) { 
     // The magic of the mute request happens here 
     if (muteRequest) { 
      if (response.statusCode >= 200 && response.statusCode <= 299) { 
       // If the status is correct, we return a success but with a null object, because the server didn't return anything 
       return Response.success(null, HttpHeaderParser.parseCacheHeaders(response)); 
      } 
     } else { 
      try { 
       // If it's not muted; we just need to create our POJO from the returned JSON and handle correctly the errors 
       String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); 
       T parsedObject = gson.fromJson(json, clazz); 
       return Response.success(parsedObject, HttpHeaderParser.parseCacheHeaders(response)); 
      } catch (UnsupportedEncodingException e) { 
       return Response.error(new ParseError(e)); 
      } catch (JsonSyntaxException e) { 
       return Response.error(new ParseError(e)); 
      } 
     } 
     return null; 
    } 

    @Override 
    public Map<String, String> getHeaders() throws AuthFailureError { 
     return headers != null ? headers : super.getHeaders(); 
    } 

    private void configureRequest() { 
     // Set retry policy 
     // Add headers, for auth for example 
     // ... 
    } 
} 

Đây là original answer trên thread khác.

0

Nếu không có phản hồi nào được mong đợi, thì có thể mở rộng thêm JsonRequest với ý nghĩ đó.

Một ví dụ trong Kotlin:

/** 
* A request containing a [JSONObject] body for a given URL, expecting an empty response. 
*/ 
class JsonObjectRequestEmptyResponse 
/** 
* Creates a new request. 
* @param method the HTTP method to use 
* @param url URL to fetch the JSON from 
* @param jsonRequest A [JSONObject] to post with the request. 
* @param listener Listener to receive a successful response 
* @param errorListener Error listener, or null to ignore errors. 
*/ 
(method: Int, url: String, jsonRequest: JSONObject, 
listener:() -> Unit, errorListener: ErrorListener?) : JsonRequest<Unit>(method, url, 
     jsonRequest.toString(), Listener<Unit> { _response -> listener() }, errorListener) { 

    override fun parseNetworkResponse(response: NetworkResponse): Response<Unit> { 
     if (response.data.isEmpty()) { 
      return Response.success(Unit, 
        HttpHeaderParser.parseCacheHeaders(response)) 
     } else { 
      return Response.error(VolleyError("unexpected data")) 
     } 
    } 
} 
Các vấn đề liên quan