本文主要列举一些遇到的retrofit 请求的问题,作为记录。
关于Retrofit的注解介绍可移步另一篇文章总结:Retrofit 2.0全部注解及注意事项
文章目录
问题一:@Field parameters can only be used with form encoding
使用post请求且参数注解为@Field时会报此错误
@POST("news/list")
Call<NewsData> getNewsData(@Field("key") String key);
错误原因是:
@Field参数只能用在表单编码(form encoding),即Content-Type: application/x-www-form-urlencoded,而默认的格式是Content-Type: application/json; charset=UTF-8;
解决方法是:
添加url编码方式的注解:@FormUrlEncoded
@FormUrlEncoded
@POST("news/list")
Call<NewsData> getNewsData(@Field("key") String key);
@FormUrlEncoded注解会将url编码转为form格式即Content-Type: application/x-www-form-urlencoded。
但是这样可能还会失败,因为可能会产生一个新的问题:
一般后台接口设计的接收参数的编码格式是json的即Content-Type: application/json; charset=UTF-8,而我们传过去的url格式为form的,就会造成url无法识别,返回错误编码415,代表是参数错误。那我们会想使用header注解指定content-type为json应该可以了吧,然而尝试后会报400的错误,所以@FormUrlEncoded注解不止是改变一个content-type那么简单,源码里还有很多和此注解相关的逻辑控制,想要具体深究的同学可以仔细跟一下源码。那这要如何解决呢?
最终解决方法为:
参数封装使用@Body:
@POST("news/list")
Call<NewsData> getNewsData(@Body("key") String key);
如果是两个以上参数就要封装到一个bean中,这样就可以解决。
如果参数只有一个或者两个我们一定会觉得这样做会很麻烦而且代码冗余很难容忍,但是暂时没有找到其他解决方法。
问题二:@Body parameters cannot be used with form or multi-part encoding.
错误原因:
其实错误信息很明确,就是@Body标签不能同时和@FormUrlEncoded、@Multipart标签同时使用。
@FormUrlEncoded
@POST("/api/getUser")
Observable<String> getUserInfo(@Body User user);
查看报错位置源码如下:
if (isFormEncoded || isMultipart) {
throw parameterError(p, "@Body parameters cannot be used with form or multi-part encoding.");
}
这样就一目了然了。