Retrofit
一、背景
Retrofit 可以将Http请求转换为Java 接口,这样我们在调用Http接口请求就跟调RPC接口一样方便。
eg:
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
二、使用方法:
QuickStart
-
引入依赖
<dependency> <groupId>com.squareup.retrofit2</groupId> <artifactId>retrofit</artifactId> <version>2.9.0</version> </dependency>
-
创建Interface
public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); }
-
Retrofit
生成实例对象Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build(); GitHubService service = retrofit.create(GitHubService.class);
-
调用
Call<List<Repo>> repos = service.listRepos("octocat");
API 介绍
Retrofit 给我们提供了非常丰富的注解,本小结主要是从使用层面介绍各个注解的用法,以及使用场景
上图::左半部分是用于发送请求的注解(对应HTTP/1.1 协议规定的HTTP请求的方法),接口方法上必有其中注解之一,右半部分是在特定Http请求场景下使用的修饰增强方法——配合左半部分一起使用。
@GET
作用:发送GET 请求
使用范围:Method
使用案例:
@GET("users/list")
// 还可以指定查询参数
@GET("users/list?sort=desc")
@Path
作用:有时候我们在请求是需要将参数作为请求路径的一部分时使用。
使用范围:Parameter
使用案例:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
@Query
作用:动态指定Url参数
使用范围:Parameter
使用案例:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
@QueryMap
作用:动态指定Url参数
使用范围:Parameter
使用案例:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
@POST、@Body
作用:@POST-发送POST请求;@Body - 讲参数转换为RequestBody 体进行传输
使用范围:@POST-Method;@Body-Parameter
使用案例:
@POST("users/new")
Call<User> createUser(@Body User user);
注意: @Body 修饰的对象在经过传输之前会使用Retrofit 指定的Converter进行转换,如果不指定Converter 智能转换RequestBody 对象
@FormUrlEncoded、@Field
作用:我们都知道Http的Post 请求,数据必须放在消息头(entity-body)中,但是协议并没有规定编码格式。服务端解析数据是根于请求头的Content-Type 标记编码格式来进行解析。@FormUrlEncoded 对应 (Content-Type: application/x-www-form-urlencoded;charset=utf-8)
使用范围:@FormUrlEncoded-Method;@@Field-
Parameter
使用案例:
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
对应Post伪代码:
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
@Multipart、@Part、@PUT
作用:对应Http的Post 请求上传文件
使用范围:@Multipart-Method;@Part-Parameter;@PUT-Method
使用案例:
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
@Headers
作用:静态指定请求头
使用范围:Method
使用案例:
@Headers({
"Accept: application/vnd.github.v3.full+json",
"User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);
注意:所有的Headers不会被重写,只是原封不动的加进请求中
@Header、@HeaderMap
作用:动态指定请求头
使用范围:Parameter
使用案例:
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
@GET("user")
Call<User> getUser(@HeaderMap Map<String, String> headers)
Retrofit 配置
CONVERTER
默认情况下Retrofit 只能反序列化http请求Body。(翻译成大白话就是@Body 只能修饰RequestBody)
但是Retrofit 给我们提供了其他类型的Converter 供我们使用,用于支持其他类型的转换
- Gson:
com.squareup.retrofit2:converter-gson
- Jackson:
com.squareup.retrofit2:converter-jackson
- Moshi:
com.squareup.retrofit2:converter-moshi
- Protobuf:
com.squareup.retrofit2:converter-protobuf
- Wire:
com.squareup.retrofit2:converter-wire
- Simple XML:
com.squareup.retrofit2:converter-simplexml
- JAXB:
com.squareup.retrofit2:converter-jaxb
- Scalars (primitives, boxed, and String):
com.squareup.retrofit2:converter-scalars
使用方式:
假设我们现在指定Gson序列化
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create()) //指定
.build();
GitHubService service = retrofit.create(GitHubService.class);
自定义CONVERTER
新建一个类继承Converter.Factory 类型,覆写其方法
abstract class Factory {
/**
* Returns a {@link Converter} for converting an HTTP response body to {@code type}, or null if
* {@code type} cannot be handled by this factory. This is used to create converters for
* response types such as {@code SimpleResponse} from a {@code Call<SimpleResponse>}
* declaration.
*/
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
return null;
}
/**
* Returns a {@link Converter} for converting {@code type} to an HTTP request body, or null if
* {@code type} cannot be handled by this factory. This is used to create converters for types
* specified by {@link Body @Body}, {@link Part @Part}, and {@link PartMap @PartMap}
* values.
*/
public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
/**
* Returns a {@link Converter} for converting {@code type} to a {@link String}, or null if
* {@code type} cannot be handled by this factory. This is used to create converters for types
* specified by {@link Field @Field}, {@link FieldMap @FieldMap} values,
* {@link Header @Header}, {@link HeaderMap @HeaderMap}, {@link Path @Path},
* {@link Query @Query}, and {@link QueryMap @QueryMap} values.
*/
public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
/**
* Extract the upper bound of the generic parameter at {@code index} from {@code type}. For
* example, index 1 of {@code Map<String, ? extends Runnable>} returns {@code Runnable}.
*/
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
/**
* Extract the raw class type from {@code type}. For example, the type representing
* {@code List<? extends Runnable>} returns {@code List.class}.
*/
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
注意事项
-
Retrofit 配置 baseUrl 必须以“/”结束;
-
Retrofit 配置 baseUrl 如果域名后配置路径,实际发请求是截取到域名结束部分;
eg:
如果配置 baseUrl : www.baidu.com/pic/xxx/eee…
实际使用是 发送请求的 baseUrl :www.baidu.com/
-
POST 、GET 等方法不允许赋值为空,如果不赋值可以使用 ”.“ 或者”/“ 代替;
eg: @POST(”.“) 或者@POST(”/“)