Повторная установка метаданных исключения IllegalArgumentException для асинхронного вызова DELETE FormUrlEncoded

Я пытаюсь сделать асинхронные POST и DELETE, которые кодируются с помощью Retrofit в Android 4.4

Вот мой клиент -

@FormUrlEncoded
@POST(INetwork.API_BASE_PREFIX + "/memberships.json")
void join(@Field("id") String id, Callback<?> cb);

@FormUrlEncoded
@DELETE(INetwork.API_BASE_PREFIX + "/memberships.json")
void leave(@Field("id") String id, Callback<?> cb);

И это исключение -

java.lang.IllegalArgumentException: IRepositoryClient.leave: FormUrlEncoded can only be specified on HTTP methods with request body (e.g., @POST).
        at retrofit.RestMethodInfo.methodError(RestMethodInfo.java:118)
        at retrofit.RestMethodInfo.parseMethodAnnotations(RestMethodInfo.java:191)
        at retrofit.RestMethodInfo.init(RestMethodInfo.java:128)
        at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:329)
        at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:264)
        at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:315)
        at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
        at retrofit.Platform$Android$2$1.run(Platform.java:142)
        at java.lang.Thread.run(Thread.java:841)

Я просмотрел источник, и это в основном, если у метода нет тела, и запрос формализован, это исключение выбрано. Также я заметил, что весь пример FormUrlEncoded работает нормально, когда он не является асинхронным, то есть у меня есть какой-то тип возврата и никакого обратного вызова - извините, я немного потерял

Должен ли я отправить пустое тело? Должен ли я отправить один и не будет ли параметров @Field достаточным?

Использование Retrofit 1.5.0

Ответ 1

RFC для HTTP неясно, разрешен ли метод DELETE иметь тело запроса или нет. Дооснащение поднимает ошибку на стороне осторожности, не имея ее.

Тем не менее, вы все равно можете включить один (при условии, что HTTP-клиент поддерживает его), используя пользовательскую аннотацию HTTP-метода.

package com.myapp;

@Target(METHOD)
@Retention(RUNTIME)
@RestMethod(value = "DELETE", hasBody = true)
public @interface BODY_DELETE {
  String value();
}

Теперь укажите свой метод интерфейса, используя пользовательскую аннотацию, которую вы определили.

@FormUrlEncoded
@BODY_DELETE(INetwork.API_BASE_PREFIX + "/memberships.json")
void leave(@Field("id") String id, Callback<?> cb);

Ответ 2

Обновленный ответ для Retofit 2.0:

У Retrofit 2 больше нет @RestMethod, поэтому вот что работает:

@FormUrlEncoded
@HTTP(method = "DELETE", path = INetwork.API_BASE_PREFIX + "/memberships.json", hasBody = true)
void leave(@Field("id") String id, Callback<?> cb);

Для модификации 2. +

@FormUrlEncoded
@HTTP(method = "DELETE", path = INetwork.API_BASE_PREFIX + "/memberships.json", hasBody = true)
Callback<?> cb(@Field("id") String id);

и для RxRetrofit 2. +

@FormUrlEncoded
@HTTP(method = "DELETE", path = INetwork.API_BASE_PREFIX + "/memberships.json", hasBody = true)
Observable<?> cb(@Field("id") String id);