Retrofit et GET à l'aide de paramètres

92

J'essaie d'envoyer une demande à l'API Google GeoCode à l'aide de Retrofit. L'interface de service ressemble à ceci:

public interface FooService {    
    @GET("/maps/api/geocode/json?address={zipcode}&sensor=false")
    void getPositionByZip(@Path("zipcode") int zipcode, Callback<String> cb);
}

Quand j'appelle le service:

OkHttpClient okHttpClient = new OkHttpClient();

RestAdapter restAdapter = new RestAdapter.Builder().setEndpoint(Constants.GOOGLE_GEOCODE_URL).setClient(new OkClient(okHttpClient)).build();

FooService service = restAdapter.create(FooService.class);

service.getPositionByZip(zipCode, new Callback<String>() {
    @Override public void success(String jsonResponse, Response response) {
       ...
    }
@Override public void failure(RetrofitError retrofitError) {
    }
});

Je reçois le stacktrace suivant:

06-07 13:18:55.337: E/AndroidRuntime(3756): FATAL EXCEPTION: Retrofit-Idle
06-07 13:18:55.337: E/AndroidRuntime(3756): Process: com.marketplacehomes, PID: 3756
06-07 13:18:55.337: E/AndroidRuntime(3756): java.lang.IllegalArgumentException: FooService.getPositionByZip: URL query string "address={zipcode}&sensor=false" must not have replace block.
06-07 13:18:55.337: E/AndroidRuntime(3756):     at retrofit.RestMethodInfo.methodError(RestMethodInfo.java:120)
06-07 13:18:55.337: E/AndroidRuntime(3756):     at retrofit.RestMethodInfo.parsePath(RestMethodInfo.java:216)
06-07 13:18:55.337: E/AndroidRuntime(3756):     at retrofit.RestMethodInfo.parseMethodAnnotations(RestMethodInfo.java:162)
06-07 13:18:55.337: E/AndroidRuntime(3756):     at 

J'ai jeté un coup d'œil à la question StackOverflow: Retrofit: plusieurs paramètres de requête dans la commande @GET? mais cela ne semblait pas applicable.

J'ai pris le code à peu près textuellement d'ici: http://square.github.io/retrofit/ donc je suis un peu perdu pour comprendre le problème.

Pensées?

Perry Hoekstra
la source

Réponses:

154

AFAIK, {...}ne peut être utilisé que comme chemin, pas à l'intérieur d'un paramètre de requête. Essayez plutôt ceci:

public interface FooService {    

    @GET("/maps/api/geocode/json?sensor=false")
    void getPositionByZip(@Query("address") String address, Callback<String> cb);
}

Si vous avez un nombre inconnu de paramètres à transmettre, vous pouvez utiliser quelque chose comme ceci:

public interface FooService {    

    @GET("/maps/api/geocode/json")
    @FormUrlEncoded
    void getPositionByZip(@FieldMap Map<String, String> params, Callback<String> cb);
}
Bart Kiers
la source
Comment ajouter plusieurs paramètres de requête
Gilberto Ibarra
2
@GilbertoIbarra err, en ajoutant plus:void getPositionByZip(@Query("address") String address, @Query("number") String number, Callback<String> cb);
Bart Kiers
9
FormUrlEncoded ne peut être spécifié que sur les méthodes HTTP avec le corps de la requête (par exemple, @POST)
jiashie
8
Mauvaise réponse ici, @FormUrlEncoded ne peut pas utiliser avec GET
mr.icetea
1
@FormUrlEncodedne fonctionne pas avec l' @GETannotation
Black_Zerg
40

@QueryMap travaillé pour moi au lieu de FieldMap

Si vous avez un tas de paramètres GET, une autre façon de les transmettre dans votre URL est un HashMap.

class YourActivity extends Activity {

private static final String BASEPATH = "http://www.example.com";

private interface API {
    @GET("/thing")
    void getMyThing(@QueryMap Map<String, String> params, new Callback<String> callback);
}

public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.your_layout);

   RestAdapter rest = new RestAdapter.Builder().setEndpoint(BASEPATH).build();
   API service = rest.create(API.class);

   Map<String, String> params = new HashMap<String, String>();
   params.put("key1", "val1");
   params.put("key2", "val2");
   // ... as much as you need.

   service.getMyThing(params, new Callback<String>() {
       // ... do some stuff here.
   });
}
}

L'URL appelée sera http://www.example.com/thing/?key1=val1&key2=val2

madhu527
la source
4

Je voulais également préciser que si vous avez des paramètres d'url complexes à construire, vous devrez les construire manuellement. c'est-à-dire que si votre requête est example.com/?latlng=-37,147, au lieu de fournir les valeurs lat et lng individuellement, vous devrez construire la chaîne latlng en externe, puis la fournir en paramètre, c'est-à-dire:

public interface LocationService {    
    @GET("/example/")
    void getLocation(@Query(value="latlng", encoded=true) String latlng);
}

Notez que le encoded=trueest nécessaire, sinon la mise à niveau encodera la virgule dans le paramètre de chaîne. Usage:

String latlng = location.getLatitude() + "," + location.getLongitude();
service.getLocation(latlng);
TheIT
la source
1

Exemple de travail complet dans Kotlin , j'ai remplacé mes clés API par 1111 ...

        val apiService = API.getInstance().retrofit.create(MyApiEndpointInterface::class.java)
        val params = HashMap<String, String>()
        params["q"] =  "munich,de"
        params["APPID"] = "11111111111111111"

        val call = apiService.getWeather(params)

        call.enqueue(object : Callback<WeatherResponse> {
            override fun onFailure(call: Call<WeatherResponse>?, t: Throwable?) {
                Log.e("Error:::","Error "+t!!.message)
            }

            override fun onResponse(call: Call<WeatherResponse>?, response: Response<WeatherResponse>?) {
                if (response != null && response.isSuccessful && response.body() != null) {
                    Log.e("SUCCESS:::","Response "+ response.body()!!.main.temp)

                    temperature.setText(""+ response.body()!!.main.temp)

                }
            }

        })
Hitesh Sahu
la source
1
Pouvez-vous mettre la définition de la méthode getWeather (params) pour plus de clarté?
supro_96