Retrofit 使用介绍

Retrofit 基于okhttp的网络请求,将http api 改造为 java interface。

  • 拥有okhttp请求网络的各种优势
  • Retrofit需要至少Java 7或Android 2.3
  • 通过注解配置请求相关参数自动生成相关代码
  • 可以简化我们网络操作的工作,提高效率和正确率
  • 支持返回各种类型的数据String json Oservable 等(如果返回数据是json,还支持很多主流json解析工具)

retrofit使用介绍

引入项目

这里直接贴出retrofit的开源地址

引入依赖:

1
compile 'com.squareup.retrofit2:retrofit:2.3.0'

官方简易使用示例

使用同步get访问https://api.github.com/users/{user}/repos ( {user} 这里代表动态用户名 )

  • 将http api 改造为 interface

    1
    2
    3
    4
    public interface GitHubService {
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
    }
  • 使用Retrofit生成GitHubService接口的实现

    1
    2
    3
    4
    5
    Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

    GitHubService service = retrofit.create(GitHubService.class);
  • 调用githubservice可以同步或(异步 推荐使用Rxjava)HTTP请求到远程服务器

    1
    Call<List<Repo>> repos = service.listRepos("octocat");

retrofit 注解介绍

请求方式

每个方法都必须具有提供请求方法和相对URL的HTTP注释。有五个内置注释:GET,POST,PUT,DELETE,和HEAD。

  • 以下代码表示:
    • 在interface 中的方法指定请求方式为:get
    • 其请求的相对路径为:users/list
      1
      @GET("users/list")
  • 如需在url添加固定参数也可以如下直接拼接
    1
    @GET("users/list?sort=desc")

URL操作

URL路径替换

可以使用方法上的替换块和参数动态更新请求URL。需使用注解:@Path。

  • 以下代码可以动态替换相对路径中的id 即:以get方式访问 baseURL + group/(groupId)/users 响应Call<List>
    1
    2
    @GET("group/{id}/users")
    Call<List<User>> groupList(@Path("id") int groupId);
    注: 必须使用相同的字符串注释相应的参数
  • 动态URL请求 以post FormUrlEncoded方式访问url响应Call
    1
    2
    @FormUrlEncoded 
    Call<UserDTO> getUserInfo(@Url String url);
URL参数添加
@Query & @QueryMap
  • 简单查询参数可用:@Query 以下示例表示:get访问 baseUrl + group/(groupId)?sort=(sort)
    1
    2
    @GET("group/{id}/users")
    Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
  • 对于相同参数多值也可以使用:@Query 以下示例表示:get访问 baseUrl + group/(groupId)?sort=(sort.get(0))&sort=(sort.get(i))…
    1
    2
    @GET("group/{id}/users")
    Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") List<String> sort);
  • 对于复杂的查询参数组合,可以使用@QueryMap 以下示例表示:get访问 baseUrl + group/(groupId)?key0=(values0)&key1=(values1)…
    1
    2
    @GET("group/{id}/users")
    Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
@Body
  • 对于请求参数比较多,不易管理可使用@Body映射对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class User{
    public int userId;
    public String userName;
    public String userAge;
    }

    //方式1 需要指定的转换器进行转换
    @POST("users/new")
    Call<User> createUser(@Body User user);
    // 方式1 调用
    Retrofit.Builder().addConverterFactory(GsonConverterFactory.create())
    createUser(user);


    //方式2
    @POST("users/new")
    Call<User> createUser(@Body RequestBody requestBody);
    // 方式2调用
    RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),User);
    createUser(body);
    注:
  • 该对象也将使用Retrofit实例上指定的转换器进行转换。如果没有加入转换器,只能RequestBody使用。
  • @Body不能与@FormUrlEncoded @Multipart共用
    关于Body使用可参考:
    Retrofit中@Body的使用
    Retrofit自定义GsonConverter处理所有请求错误情况
@FormUrlEncoded & @Field & @FieldMap
  • FormUrlEncoded
    • 自动将请求参数的类型调整为application/x-www-form-urlencoded
  • Field
    • Post请求需要把请求参数放置在请求体中,而非拼接在url后面
    • encoded参数为false的话,key-value-pair将会被编码,即将中文和特殊字符进行编码转换(默认false,true不编码)
  • FieldMap
    • 类似于上述QueryMap,方便用于多个参数随意组合
      1
      2
      3
      4
      5
      6
      7
      @FormUrlEncoded
      @POST("user/edit")
      Call<User> updateUser(@Field("first_name") String first, @Field(value = "last_name", encoded = true) String last);

      @FormUrlEncoded
      @POST("book/reviews")
      Call<String> addReviews(@FieldMap Map<String, String> fields);
      注:
  • FormUrlEncoded不能用于Get请求
    一般用于多文件上传
    @Multipart & @Part
  • Multipart
    • 使用多部分请求
  • Part
    • 每部分请求的RequestBody
      1
      2
      3
      @Multipart
      @PUT("user/photo")
      Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
      多文件上传参考:
      Retrofit用法详解

Headers 操作

固定请求头
1
2
3
4
5
6
7
8
9
10
@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();

// 方法调用
//service.widgetList();

// 请求头
// GET http://.../widget/list HTTP/1.1
// Cache-Control: max-age=640000
1
2
3
4
5
6
7
8
9
10
11
12
13
@Headers({
"Accept: application/vnd.github.v3.full+json",
"User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);
// 方法调用
//service.getUser(username);

// 请求头
// GET http://.../users/username HTTP/1.1
// Accept: application/vnd.github.v3.full+json
// User-Agent: Retrofit-Sample-App

注:

  • header不会相互覆盖。所有名称相同的header都将包含在请求中。
  • 对照okhttp的header(key, value)
  • Content-Range 断点下载相关参考
    动态请求头
    1
    2
    @GET("user")
    Call<User> getUser(@Header("Authorization") String authorization)
    注:
  • 存在的header会覆盖更新。
  • 可以使用Interceptors指定需要添加到每个请求中的header
  • 对照okhttp的addHeader(key, value)

其他

同步异步
  • 参考okhttp Call 示例
  • 可直接调用同步使用Rxjava完成异步操作
converter 转换器

默认情况下,Retrofit只能将HTTP体反序列化为OkHttp的ResponseBody类型,它只能接受它的RequestBody类型@Body。
可以添加转换器来支持其他类型。官方支持有以下几个:

  • 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
  • Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

以下是使用GsonConverterFactory类生成GitHubService使用Gson进行反序列化的接口的实现的示例:

1
2
3
4
5
6
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.build();

GitHubService service = retrofit.create(GitHubService.class);

注:

  • 如果你需要自定义支持其他内容格式,你可以自行扩展Converter.java并在构建适配器时传递一个实例。

PROGUARD 混淆相关

如果你正在使用混淆器在你的项目中添加以下代码到您的配置:

1
2
3
4
5
6
7
8
# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions

参考