2013-10-06 5 views
6

Jedną z rzeczy, których nigdy nie lubiłem o Gsonie, jest fakt, że musisz przekazać obiekt klasy lub typToken na podstawie, jeśli dostajesz przedmiot lub listę przedmiotów . Teraz, próbując użyć Volley z Gsonem, ten problem utrzymuje się i próbuję utworzyć klasę GsonRequest, która może być użyta dla obu rzeczy.Używanie Volley i Gson: Analiza pozycji i listy przedmiotów

Moje rozwiązanie jest dość brzydkie, dwa różne konstruktory: jeden pobierający parametr Class<T>, a drugi pobierający parametry Type. Następnie w nazwie parseNetworkResponse, gson.fromJson jest wywoływane z jednym z tych pól, pamiętając, że jeden musi być null.

Każdy pomysł, jak lepiej to wdrożyć? (Nie lubię o GsonRequest a GsonCollectionRequest niemal równych klas)

Mój kod tutaj:

public class GsonRequest<T> extends Request<T> { 

    private final Gson gson; 
    private final Class<T> clazz; 
    private final Type type; 
    private final Listener<T> listener; 
    private final Map<String, String> headers; 
    private final Map<String, String> params; 

    public GsonRequest(int method, String url, Gson gson, Class<T> clazz, Map<String, String> headers, Map<String, String> params, Listener<T> listener, ErrorListener errorListener) { 
     super(method, url, errorListener); 
     this.gson = gson; 
     this.clazz = clazz; 
     this.type = null; 
     this.listener = listener; 
     this.headers = headers; 
     this.params = params; 
    } 

    public GsonRequest(int method, String url, Gson gson, Type type, Map<String, String> headers, Map<String, String> params, Listener<T> listener, ErrorListener errorListener) { 
     super(method, url, errorListener); 
     this.gson = gson; 
     this.clazz = null; 
     this.type = type; 
     this.listener = listener; 
     this.headers = headers; 
     this.params = params; 
    } 

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

    @Override 
    protected Map<String, String> getParams() throws AuthFailureError { 
     return this.params != null ? this.params : super.getParams(); 
    } 

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

      if (this.clazz != null) { 
       return Response.success(
         this.gson.fromJson(new String(response.data, HttpHeaderParser.parseCharset(response.headers)), this.clazz), 
         HttpHeaderParser.parseCacheHeaders(response)); 
      } else { 
       return (Response<T>) Response.success(
         this.gson.fromJson(new String(response.data, HttpHeaderParser.parseCharset(response.headers)), this.type), 
         HttpHeaderParser.parseCacheHeaders(response)); 
      } 

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

    @Override 
    protected void deliverResponse(T response) { 
     this.listener.onResponse(response); 
    } 

} 
+0

Klasa 'Klasa' faktycznie implementuje interfejs' Type', więc naprawdę nie konstruktor, który przyjmuje argument "Klasa" jako argument. –

+0

Humm ... byłem prawie pewien, że dostałem jakiś błąd, przekazując 'Type' do' gson.fromJson', kiedy chciałem, aby jakiś element został sparsowany. W każdym razie, właśnie wypróbowałem to przy użyciu 'Type' i zadziałało, więc może potrzebuję użyć' Type', jak mówisz. Napisz to jako odpowiedź, a ja ją przyjmuję :) – luixal

+0

Zobacz ten artykuł, który dokładnie to wyjaśnia. https://goo.gl/nl2DfN – Sotti

Odpowiedz

3

Można utworzyć nowy GsonRequest użyciu TypeToken jako parametr Type.

Użyj ogólnego GsonRequest w ten sposób GsonRequest.

Tworzenie prostego wniosku o klasie Gson ...

new GsonRequest<MyClass>(Request.Method.GET, uriBuilder.build().toString(), 
        MyClass.class, null, mResponseListener, mReponseErrorListener)); 

lub utworzyć typ dla ArrayList ...

Type type = new TypeToken<ArrayList<MyClass>>() {}.getType(); 
new GsonRequest<ArrayList<MyClass>>(Request.Method.GET, uriBuilder.build().toString(), 
        type, null, mResponseListListener, mReponseErrorListener)); 
+0

czy chcesz dodać nowy/inny konstruktor do swojej klasy gsonRequest? – Zapnologica

+0

Twój przykład nie działa dla mnie, czy użyłeś tego w kodzie? – Zapnologica

+0

Tak, i to działa dla mnie. Możesz być bardziej dokładny? Jakiego rodzaju błąd dostaniesz? – jgonza73

0

użyłem wniosek JSONObject z Volley i używane Response.ToString(), aby przetworzyć ciąg Json na klasę przez Gson.

Gson gson = new Gson(); 
ClassName obj = gson.fromJson(response.ToString(),ClassName.class); 

Teraz masz obj ze wszystkimi danymi.

+0

To jednak nie robi parsowanie wątku roboczego. – Zapnologica

3

Użyłem następującej metody do analizy listy JSON. Jako pierwszy nie wysyłaj klasy do konstruktora, zamiast tego przeprowadź klasę Type z pakietu reflect.

Moja klasa wygląda następująco:

public class DownloadRequest<T> extends Request<T> { 

private final Gson gson = new Gson(); 
private final Type type; 
private final Map<String, String> params; 
private final Response.Listener<T> listener; 

public DownloadRequest(int method, String url, Map<String, String> params, Type type, Response.Listener<T> listener, Response.ErrorListener errorListener) { 
    super(method, url, errorListener); 
    this.type = type; 
    this.params = params; 
    this.listener = listener; 
} 

@Override 
protected Response<T> parseNetworkResponse(NetworkResponse networkResponse) { 

    try { 
     String json = new String(networkResponse.data, HttpHeaderParser.parseCharset(networkResponse.headers)); 
     T parseObject = gson.fromJson(json, type); 
     return Response.success(parseObject,HttpHeaderParser.parseCacheHeaders(networkResponse)); 
    } catch (UnsupportedEncodingException e) { 
     e.printStackTrace(); 
    } 

    return null; 
} 

@Override 
protected void deliverResponse(T t) { 
    listener.onResponse(t); 
} 

}

Linia T parseObject = gson.fromJson(json, type); ważne jest, aby ustawić przed wywołaniem metody Request.success.

+0

Dzięki. Zastosowano twoją metodę parseNetworkResponse (...) dla typu parametru. Dobrze pracować. – Godekere

Powiązane problemy