android - setsupportactionbar - Convertidor personalizado para la modificación
programacion android pdf 2018 (1)
Estoy tratando de usar un convertidor personalizado para Retrofit
RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint(BuildConfig.BASE_SERVER_ENDPOINT)
.setClient(new OkClient(client)).setConverter(new CitationResponseConverter())
.setLogLevel(RestAdapter.LogLevel.FULL);
a continuación es mi convertidor personalizado
public class CitationResponseConverter implements Converter {
@Override
public Object fromBody(TypedInput typedInput, Type type) throws ConversionException {
try {
InputStream in = typedInput.in(); // convert the typedInput to String
String string = fromStream(in);
in.close(); // we are responsible to close the InputStream after use
if (String.class.equals(type)) {
return string;
} else {
return new Gson().fromJson(string,
type); // convert to the supplied type, typically Object, JsonObject or Map<String, Object>
}
} catch (Exception e) { // a lot may happen here, whatever happens
throw new ConversionException(
e); // wrap it into ConversionException so retrofit can process it
}
}
@Override
public TypedOutput toBody(Object object) {
return null;
}
private static String fromStream(InputStream in) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder out = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
out.append("/r/n");
}
return out.toString();
}
}
Estoy teniendo el siguiente error
retrofit.RetrofitError: method POST must have a request body.
al intentar hacer esta llamada api
@POST("/service/citations")
Observable<CitationMain> getCitations(@Body CitationRequestBody body);
Supongo que el convertidor está anulando la solicitud de la llamada de API, ¿cómo puedo evitar eso y pasar el cuerpo de solicitud definido en el servicio de actualización?
Respuesta:
{
"citations": [
{
"coverdatestart": "2015-05-01",
"coverimage": [
"09699961/S0969996115X00040/cov200h.gif",
"09699961/S0969996115X00040/cov150h.gif"
],
"pubyear": "2015",
"refimage": [
"09699961/S0969996115X00040/S0969996115000522/gr1-t.gif",
"09699961/S0969996115X00040/S0969996115000522/gr1.jpg"
],
"volissue": "Volume 77",
"volume": "77"
},
{
"pubdatetxt": "19700101",
"refimage": "mma:otto_4_9781455748600/9781455748600_0020",
}
]
}
Haría algo así:
public class StringList extends ArrayList<String> {
// Empty on purpose. The class is here only to be recognized by Gson
}
public class CitationMain {
@SerializedName("field_name_here")
StringList values;
// Your other fields
}
Luego, al crear el RestAdapter:
public class StringListDeserializer implements JsonDeserializer<StringList> {
@Override
public StringList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext
context) throws JsonParseException {
StringList value = new StringList();
if (json.isJsonArray()) {
for (JsonElement element : json.getAsJsonArray()) {
value.add(element.getAsString());
}
} else {
value.add(json.getAsString());
}
return value;
}
}
Y entonces:
Gson gson = new GsonBuilder()
.registerTypeAdapter(StringList.class, new StringListDeserializer())
.create();
RestAdapter.Builder builder = new RestAdapter.Builder()
//...
.setConverter(new GsonConverter(gson));
No es ideal, ya que el objeto es personalizado, pero cualquier otra solución que se me ocurra en este momento es mucho más compleja.
El deserializador aquí está registrado específicamente para los campos declarados como StringList
, y manejará el caso de una sola cadena, así como el caso de una matriz de cadenas. Cualquier otro tipo de campo usará el proceso de deserialización predeterminado.