Retrofit: ¿Cómo especificar parámetros separados por comas en la solicitud?

Estoy tratando de refactorizar mi código para utilizar Retrofit (de Volley) para algunas llamadas API Foursquare, pero no han encontrado un ejemplo adecuado que muestra cómo especificar un parámetro de consulta que tiene 2 valores separados por una coma.

Mi URL base es la siguiente:

public static final String VENUES_BASE_URL = "https://api.foursquare.com/v2/venues"; 

El resto de mi url es como esto:

 "?ll=40.7,50.2&limit=50&radius=25000&v=20140909&venuePhotos=1&oauth_token=xxyyxx"; 

Primera implementación para mi interfaz:

 public interface Fourquare { @GET("/explore?ll={p1},{p2}&limit=50&radius=25000&v=20140905&venuePhotos=1&oauth_token=xxyyxx") Response getVenues(@Path("p1") String param1, @Path("p2") String param2); } 

Y luego hizo la solicitud como esta:

 RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(ConfigConstants.VENUES_BASE_URL) .build(); Fourquare fourquare = restAdapter.create(Fourquare.class); Response myResponse = fourquare.getVenues("50", "75"); 

Sin embargo, lo anterior me dio el siguiente error:

 retrofit.RetrofitError: Fourquare.getVenues: URL query string "ll={p1},{p2}&limit=50&radius=25000&v=20140905&venuePhotos=1&oauth_token=xxyyxx" must not have replace block. 

2ª implementación (Después de ver algunas de las respuestas de SO que usan los parámetros de consulta NOTA: Una vez que descubro la ll ll llamada de parámetro tendremos el token como parámetro):

 @GET("/explore&limit=50&radius=25000&v=20140905&venuePhotos=1&oauth_token=xxyyxx") void getVenues(@Query("ll") String ll, Callback<String> cb); 

Con la llamada real como esto:

 fourquare.getVenues("50,75", new Callback<String>() { @Override public void success(String s, Response response) { Log.d(TAG, "Successful run!"); } @Override public void failure(RetrofitError error) { Log.d(TAG, "Failed run!"); } }); 

Con la implementación anterior el método failure () siempre se llama, así que todavía hay algo mal con mi código. ¿Puede alguien dar algunas sugerencias sobre la manera correcta de implementar esta llamada? Estoy más seguro de que el problema es con el "ll?" parámetro.

Actualización: Después de activar el registro, esta es la URL final que recibo de Retrofit: https://api.foursquare.com/v2/venues/explore&limit=50&radius=25000&v=20140909&venuePhotos=1&oauth_token=xxyyxx?ll=30.26%2C-97.74

Parece que el servidor Foursquare no le gusta el? Ll parámetro al final de la url y debe ser colocado de forma explícita después de ../v2/venues/explore como que está funcionando bien cuando un lugar de la solicitud a través del navegador.

¿Hay alguna solución para evitar esta limitación de la API?

3ª puesta en práctica (9/17/14) Con la sugerencia de colriot pude resolver el código de respuesta de 400 que estaba recibiendo con mi implementación anterior. Todavía estoy teniendo un problema de velocidad con GSON por lo que buscan sugerencias sobre cómo solucionarlo. Específicamente, mi implementación de Retrofit tarda más en mostrar mis resultados en comparación con Volley, así que me pregunto si hay una mejor manera de implementar la devolución de llamada.

Interfaz Cuadrangular

 public interface Fourquare { @GET("/explore?limit=50&radius=25000&v=20140909&venuePhotos=1&oauth_token=xxyyxx") void getVenues(@Query("ll") String ll, Callback<Object> cb); } 

Llamada RestAdapter

 RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(ConfigConstants.VENUES_BASE_URL) .build(); Foursquare foursquare = restAdapter.create(Foursquare.class); foursquare.getVenues("30.26,-97.74", new Callback<Object>() { @Override public void success(Object o, Response response) { Log.d(TAG, "Success!"); // Parse response GsonBuilder gsonBuilder = new GsonBuilder(); Gson gson = gsonBuilder.create(); JsonParser parser = new JsonParser(); String response2 = gson.toJson(o); JsonObject data = parser.parse(response2).getAsJsonObject(); // Populate data model MetaResponse metaResponse = gson.fromJson(data.get("meta"), MetaResponse.class); VenuesExploreResponse myResponse = gson.fromJson(data.get("response"), VenuesExploreResponse.class); // Store results from myResponse in List } @Override public void failure(RetrofitError error) { Log.d(TAG, "Failures!"); } }); 

El problema actual con la implementación de devolución de llamada anterior es que tarda más (aproximadamente 1 segundo) que con Volley para analizar y mostrar los resultados. El bloque GsonBuilder / Gson / JsonParser es exactamente el mismo que en mi método Volley onResponse (String response) excepto para ese objeto intermedio "response2", por lo que definitivamente este paso intermedio / extra es el cuello de botella. Estoy buscando sugerencias sobre cómo implementar mejor el análisis de Gson. Si esto puede encajar mejor como una pregunta nueva / separada lo haré.

Así que, como ya hemos descubierto el problema estaba en ? -> & typo. Pero una cosa más a mencionar es que Retrofit puede aceptar objetos complejos como parámetros de llamada. Entonces String.valueOf(object) será llamado para convertir el objeto en Query / Path param.

En tu caso podrías definir clases personalizadas así:

 class LatLng { private double lat; private double lng; ... @Override public String toString() { return String.format("%.1f,%.1f", lat, lng); } } 

Y refactorice su método de punto final de esa manera:

 @GET("/explore?limit=50&radius=25000&v=20140905&venuePhotos=1&oauth_token=xxyyxx") void getVenues(@Query("ll") LatLng ll, Callback<String> cb); 

Acerca de analizar la respuesta:

  • Nunca cree objetos Gson directamente en la devolución de llamada. Es simplemente demasiado pesado. Utilice el que usted proporciona a RestAdapter .
  • ¿Por qué mezclas JsonParser y Gson ? Son herramientas diferentes para básicamente el mismo problema.
  • Hacer uso del mecanismo de conversión incorporado de Retrofit;)

De palabras a código:

 public class FoursquareResponse<T> { private MetaResponse meta; private T response; // getters } 

En total:

 @GET("/explore?limit=50&radius=25000&v=20140905&venuePhotos=1&oauth_token=xxyyxx") void getVenues(@Query("ll") LatLng ll, Callback<FoursquareResponse<VenuesExploreResponse>> cb); ... foursquare.getVenues(LatLng.valueOf(30.26, -97.74), new Callback<FoursquareResponse<VenuesExploreResponse>>() { @Override public void success(FoursquareResponse<VenuesExploreResponse> r, Response response) { MetaResponse metaResponse = r.getMeta; VenuesExploreResponse myResponse = r.getResponse(); // Store results from myResponse in List } @Override public void failure(RetrofitError error) { Log.d(TAG, "Failures!"); } }); 

Sólo urlencode sus argumentos separados por coma, coma =% 2

Intente agregar todos los parámetros de consulta (fijos y variables) en orden válido. quiero decir

 @GET("/explore") Response getVenues(@Query("ll") ll, @Query("limit") limit, @Query("radius") radius, @Query("v") v, @Query("venuePhotos") venuePhotos, @Query("oauth_token") oauth_token); 

Y wrap llamada con función que tienen params fijos como constante

Puede utilizar @EncodedQuery :

 @GET("/explore&limit=50&radius=25000&v=20140905&venuePhotos=1&oauth_token=xxyyxx") void getVenues(@EncodedQuery("ll") LatLng ll, Callback<String> cb); 
  • Consulta GET con json - Retrofit 2.0
  • ¿Es posible mostrar la barra de progreso cuando se descarga a través de Retrofit 2 Asynchronous?
  • Mapa json a objeto con retrofit (GSON)
  • No se puede analizar el error en Retrofit 2
  • Publicar campos en este formato con Retrofit
  • Retrofit 2.0 java.lang.IllegalStateException: Se esperaba BEGIN_ARRAY pero era STRING
  • Configuración de Android studio 1.1.0 minifyEnabled true causando problemas con la aplicación
  • ¿Cómo puedo utilizar Retrofit para POST un complejo JSON parámetro
  • Realm + Retrofit + Rxjava
  • Desbordamiento de pila al utilizar Retrofit rxjava concatWith
  • Problema con Retrofit y simple - intento de hacer un lector de RSS para Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.