Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装,网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装

添加依赖

1
2
3
4
5
implementation 'com.squareup.retrofit2:retrofit:2.9.0'//
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'//retrofit gson支持库
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'//retrofit rxJava支持库

implementation 'com.google.code.gson:gson:2.8.9'//gson

创建接口

Retrofit将 Http请求 抽象成 Java接口:采用 注解 描述网络请求参数 和配置网络请求参数

1
2
3
4
5
6
7
8
9
10
11
public interface GetRequest_Interface {

@GET("openapi.do?keyfrom=abc&key=2032414398&type=data&doctype=json&version=1.1&q=car")
Call<Reception> getCall(@Field("name") String name);

// @GET注解的作用:采用Get方法发送网络请求
// getCall() = 接收网络请求数据的方法
// 其中返回类型为Call<*>,*是接收数据的类(即上面定义的Translation类)
// 如果想直接获得Responsebody中的内容,可以定义网络请求返回值为Call<ResponseBody>

}

创建Retrofit实例

1
2
3
4
5
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://fanyi.youdao.com/") //设置网络请求的Url地址
.addConverterFactory(GsonConverterFactory.create()) //设置数据解析器
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();

发送请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 创建 网络请求接口 的实例
GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
//对 发送请求 进行封装
Call<ResponseBody> call = request.getCall("");

//异步请求
call.enqueue(new Callback<ResponseBody>() {
//请求成功时回调
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
//请求处理,输出结果
try {
Log.d(TAG, "onResponse: " + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
//请求失败时候的回调
@Override
public void onFailure(Call<ResponseBody> call, Throwable throwable) {
Log.d(TAG, "onFailure: ");
}
});
//同步请求
try {
Response<ResponseBody> response = call.execute();
Log.d(TAG, "Sync: " + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}

注解

网络请求方法

1.@GET、@POST、@PUT、@DELETE、@HEAD分别对应 HTTP中的网络请求方式
2.@HTTP替换@GET、@POST、@PUT、@DELETE、@PATH、@HEAD、@OPTIONS注解的作用 及 更多功能拓展
具体使用:通过属性method、path、hasBody进行设置

1
2
3
4
5
6
7
8
9
/**
* method:网络请求的方法(区分大小写)
* path:网络请求地址路径
* hasBody:是否有请求体
*/
@HTTP(method = "GET", path = "blog/{id}", hasBody = false)
Call<ResponseBody> getCall(@Path("id") int id);
// {id} 表示是一个变量
// method 的值 retrofit 不会做处理,所以要自行保证准确

标记

  1. @FormUrlEncoded 请求体是一个Form表单
    表示发送form-encoded的数据,每个键值对需要用@Filed来注解键名,随后的对象需要提供值。
  2. @Multipart 请求体是一个支持文件上传的Form表单
    表示发送form-encoded的数据(适用于 有文件 上传的场景),每个键值对需要用@Part来注解键名,随后的对象需要提供值。
  3. @Streaming 返回的数据以流的形式返回 用于返回数据较大的场景 (如果没有使用该注解,默认把数据全部载入内存,之后存取数据也是从内存中读取)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface GetRequest_Interface {
/**
*表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
* <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值
*/
@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);

/**
* {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
* 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),
*/
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);

}

网络请求参数

  1. @Header & @Headers
    添加请求头 & 添加不固定的请求头
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // @Header
    @GET("user")
    Call<User> getUser(@Header("Authorization") String authorization)

    // @Headers
    @Headers("Authorization: authorization")
    @GET("user")
    Call<User> getUser()

    // 以上的效果是一致的。
    // 区别在于使用场景和使用方式
    // 1. 使用场景:@Header用于添加不固定的请求头,@Headers用于添加固定的请求头
    // 2. 使用方式:@Header作用于方法的参数;@Headers作用于方法
  2. @Body
    以 Post方式 传递 自定义数据类型 给服务器,如果提交的是一个Map,那么作用相当于 @Field,不过Map要经过 FormBody.Builder 类处理成为符合 Okhttp 格式的表单,如:
    1
    2
    FormBody.Builder builder = new FormBody.Builder();
    builder.add("key","value");
  3. @Field & @FieldMap
    发送 Post请求 时提交请求的表单字段,与 @FormUrlEncoded 注解配合使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public interface GetRequest_Interface {
    /**
    *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
    * <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值
    */
    @POST("/form")
    @FormUrlEncoded
    Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);

    /**
    * Map的key作为表单的键
    */
    @POST("/form")
    @FormUrlEncoded
    Call<ResponseBody> testFormUrlEncoded2(@FieldMap Map<String, Object> map);

    }
  4. @Part & @PartMap
    发送 Post请求 时提交请求的表单字段,与@Field的区别:功能相同,但携带的参数类型更加丰富,包括数据流,所以适用于 有文件上传 的场景,与 @Multipart 注解配合使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public interface GetRequest_Interface {

    /**
    * {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
    * 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),
    */
    @POST("/form")
    @Multipart
    Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);

    /**
    * PartMap 注解支持一个Map作为参数,支持 {@link RequestBody } 类型,
    * 如果有其它的类型,会被{@link retrofit2.Converter}转换,如后面会介绍的 使用{@link com.google.gson.Gson} 的 {@link retrofit2.converter.gson.GsonRequestBodyConverter}
    * 所以{@link MultipartBody.Part} 就不适用了,所以文件只能用<b> @Part MultipartBody.Part </b>
    */
    @POST("/form")
    @Multipart
    Call<ResponseBody> testFileUpload2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file);

    @POST("/form")
    @Multipart
    Call<ResponseBody> testFileUpload3(@PartMap Map<String, RequestBody> args);
    }
  5. @Query和@QueryMap
    用于 @GET 方法的查询参数(Query = Url 中 ‘?’ 后面的 key-value)
    如:url = http://www.println.net/?cate=android,其中,Query = cate
    配置时只需要在接口方法中增加一个参数即可:
    1
    2
    3
    4
      @GET("/")    
    Call<String> cate(@Query("cate") String cate);

    // 其使用方式同 @Field与@FieldMap,这里不作过多描述
  6. @Path
    URL地址的缺省值
    1
    2
    3
    4
    5
    6
    7
    public interface GetRequest_Interface {

    @GET("users/{user}/repos")
    Call<ResponseBody> getBlog(@Path("user") String user );
    // 访问的API是:https://api.github.com/users/{user}/repos
    // 在发起请求时, {user} 会被替换为方法的第一个参数 user(被@Path注解作用)
    }
  7. @Url
    直接传入一个请求的 URL变量 用于URL设置
    1
    2
    3
    4
    5
    6
    7
    8
    public interface GetRequest_Interface {

    @GET
    Call<ResponseBody> testUrlAndQuery(@Url String url, @Query("showAll") boolean showAll);
    // 当有URL注解时,@GET传入的URL就可以省略
    // 当GET、POST...HTTP等方法中没有设置Url时,则必须使用 {@link Url}提供

    }