Android 为异步 FormUrlEncoded DELETE 调用改造抛出 IllegalArgumentException 异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22572301/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:11:07  来源:igfitidea点击:

Retrofit throwing IllegalArgumentException exception for asynchronous FormUrlEncoded DELETE call

androidposthttp-postretrofithttp-delete

提问by Rickster

I'm trying to make an asynchronous POST and DELETE which is form url encoded using Retrofit in Android 4.4

我正在尝试制作一个异步 POST 和 DELETE,它是在 Android 4.4 中使用 Retrofit 编码的表单 url

Here is my client -

这是我的客户——

@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);

And this is the exception -

这是个例外——

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.access0(RestAdapter.java:264)
        at retrofit.RestAdapter$RestHandler.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.run(Platform.java:142)
        at java.lang.Thread.run(Thread.java:841)

I looked through the source and it basically if the method doesn't have a body and the request is formurlencoded, this exception is thrown. Also I noticed that all example of FormUrlEncoded work fine when it is not asynchronous, i.e. I have a return type of some sort and no callback - sorry I'm a little lost

我查看了源代码,基本上如果该方法没有主体并且请求是格式编码的,则会引发此异常。我还注意到 FormUrlEncoded 的所有示例在非异步时都可以正常工作,即我有某种类型的返回类型并且没有回调 - 对不起,我有点迷茫

Should I send an empty body? Am I required to send one and won't the @Field parameters suffice?

我应该发送一个空的身体吗?我是否需要发送一个@Field 参数是否足够?

Using Retrofit 1.5.0

使用改造 1.5.0

回答by Jake Wharton

The RFC for HTTP is unclear on whether or not the DELETE method is allowed to have a request body or not. Retrofit is raising an error on the side of caution by not having one.

HTTP 的 RFC 不清楚是否允许 DELETE 方法具有请求正文。出于谨慎的考虑,Retrofit 会因为没有 Retrofit 而引发错误。

However, you can still include one (assuming the HTTP client supports it) by using a custom HTTP method annotation.

但是,您仍然可以通过使用自定义 HTTP 方法注释来包含一个(假设 HTTP 客户端支持它)。

package com.myapp;

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

Now specify your interface method using the custom annotation that you defined.

现在使用您定义的自定义注释指定您的接口方法。

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

回答by radu122

Updated answer for Retrofit 2.0:

Retrofit 2.0 的更新答案:

Retrofit 2 doesn't seem to have @RestMethod any more, so here is what works:

Retrofit 2 似乎不再有 @RestMethod,所以这里是有效的:

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

For retrofit 2.+

用于改造 2.+

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

and for RxRetrofit 2.+

和 RxRetrofit 2.+

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