2016-05-19 4 views
2

Ich habe eine API-Antwort, die generisch Daten für verschiedene Aktivitäten unserer Anwendung zurückgeben soll. Um die Anwendung so generisch und flexibel wie möglich zu gestalten, haben wir eine API eingerichtet, um eine Sammlung von URLs bereitzustellen, die zur Erstellung verschiedener Zeilen für unsere Aktivitäten verwendet werden können. Unser Basisobjekt wie folgt aussieht:Retrofit-Methode Return-Platzhalter

public class BaseApiObject { 

    @SerializedName("apiVersion") 
    private String apiVersion = null; 
    @SerializedName("totalResults") 
    private Integer totalResults = null; 
} 

Unsere Antwort für die Aktivität wie folgt aussieht:

public class ActivityApiResponse extends BaseApiObject { 
    @SerializedName("results") 
    private List<ScreenItem> results = new ArrayList<>(); 
} 

Und die ScreenItem wie folgt aussehen:

public class ScreenItem extends BaseApiObject { 
    @SerializedName("apiUrls") 
    private List<String> apiUrls = new ArrayList<>() ; 
} 

Ich möchte in der Lage sein, etwas zu tun so mit Nachrüstung:

@GET("{url}") 
Call<? extends BaseApiObject> getUrl(@Path("url") String url); 

Wir wissen, dass jede Anforderung, die wir machen, ein BaseApiObject zurückgibt, aber wir sind unsicher, welchen Objekttyp wir tatsächlich zurückgeben werden - und einige dieser URLs werden eine Liste vieler verschiedener Objekttypen zurückgeben.

Wir erhalten die folgende Fehlermeldung:

java.lang.IllegalArgumentException: Method return type must not include a type variable or wildcard: retrofit2.Call<? extends com.company.BaseApiObject> 

Gibt es eine Möglichkeit mit Retrofit dieses Szenario zu behandeln oder muß ich die BaseApiObject zurückzukehren, und dann eine benutzerdefinierte Gson Deserializer verwenden, um tatsächlich den richtigen Objekttyp zurückgeben (s)?

Antwort

1

Am Ende musste ich meinen eigenen Deserializer erstellen. Ich nahm den JsonDeserializationContext und analysierte dann meine Elemente basierend auf dem Typ, der in der JSON-Antwort zurückgegeben wurde.

Zum Beispiel meine Json annehmen sah aus wie:

{ "shapes": 
    [ 
    {"type": "circle", "radius": 2}, 
    {"type": "rectangle", "width": 3, "height": 2}, 
    {"type": "triangle", "sides": [3, 4, 5]} 
    ], 
    "apiVersion": "0.1.0", 
    "totalResults": "3" 
} 

In meinem Deserializer, ich an der Art der Formen in einer Schleife aussehen würde, und so etwas wie:

switch(jsonObject.get("type").getAsString()) { 
    case "circle": 
     return context.deserialize(jsonObject, Circle.class); 
     break; 

    case "rectangle": 
     return context.deserialize(jsonObject, Rectangle.class); 
     break; 

    case "triangle": 
     return context.deserialize(jsonObject, Triangle.class); 
     break; 

    default: 
     return context.deserialize(jsonObject, Shape.class); 
     break; 
}