【问题标题】:Retrofit throwing IllegalArgumentException exception for asynchronous FormUrlEncoded DELETE call改造为异步 FormUrlEncoded DELETE 调用抛出 IllegalArgumentException 异常
【发布时间】:2014-04-29 14:52:23
【问题描述】:

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

这是我的客户 -

@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,则会引发此异常。我还注意到,FormUrlEncoded 的所有示例在非异步时都可以正常工作,即我有某种返回类型并且没有回调 - 抱歉,我有点迷路了

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

使用改造 1.5.0

【问题讨论】:

  • 没有@FormUrlEncoded 就不行吗?那是内容编码,delete好像没有内容。
  • 1.不能在没有编码的情况下使用字段参数 - 如果我这样做,则会出现异常 java.lang.IllegalArgumentException:@Field 参数只能与表单编码一起使用。 (参数 #1)。 2.删除确实有内容,有Id

标签: android post http-post retrofit http-delete


【解决方案1】:

HTTP 的 RFC 不清楚是否允许 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);

【讨论】:

  • 如此简单且非常灵活。我喜欢改造。
  • 如何在 json 中得到响应
【解决方案2】:

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

【讨论】:

  • 救了我的命! path = "你的 api url"
  • 如何在 json 中得到响应
猜你喜欢
  • 1970-01-01
  • 2016-07-10
  • 1970-01-01
  • 2012-02-03
  • 1970-01-01
  • 2018-01-28
  • 2016-03-24
  • 1970-01-01
  • 2013-01-01
相关资源
最近更新 更多