Retrofit2使用简介

Retrofit是什么

来自官网的介绍:

A type-safe HTTP client for Android and Java

简单来说就是一个HTTP请求工具,与volley功能类似,都是用于简化HTTP请求的库。但是相比其他工具,Retrofit的解耦更彻底:例如通过注解来配置请求参数,根据需求来选择使用不同的CallAdapter(请求适配器,如:RxJava,Java8, Guava)、Converter(反序列化工具,如json, protobuff, xml, moshi)等。

Retrofit如何使用

添加依赖

在AndroidStudio的项目中,在build.gradle文件中添加以下引用:

//retrofit jar
compile 'com.squareup.retrofit2:retrofit:2.0.2'
//反序列化json工具
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

根据需求还可引入更多转换器:

  • Gson: com.squareup.retrofit:converter-gson
  • Jackson: com.squareup.retrofit:converter-jackson
  • Moshi: com.squareup.retrofit:converter-moshi
  • Protobuf: com.squareup.retrofit:converter-protobuf
  • Wire: com.squareup.retrofit:converter-wire
  • Simple XML: com.squareup.retrofit:converter-simplexml

创建Retrofit实例

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("...")
        .client(myClient())
        .addConverterFactory(GsonConverterFactory.create(myGson()))
        .addCallAdapterFactory(MyCallAdpater.create())
        .build();

其中:

可以使用okhttp自定义拦截器:

public OkHttpClient myClient(){
    OkHttpClient client = new OkHttpClient();
    client.interceptors().add(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            return null;
        }
    });
    return client;
}

可以使用自定义Gson对象:例如一些格式化的定义

public Gson myGson(){
    Gson gson = new GsonBuilder()
            .setDateFormat("yyyy-MM-dd")
            .create();
    return gson;
}

可以根据需求自定义CallAdapter,或者使用retrofit提供的一些可用的CallAdapter模块。其中最流行的就是集成RxJava的CallAdapter

new Retrofit.Builder()
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build();

创建HTTP API接口

public interface CyyHttpService {
    @GET("{token}/account/total/fetch")
    Call<ResponseBody<String>> getTotal(@Path("token") String token);

    @GET("tasks")
    Call<PageDataDTO<HistoryTaskDTO>> getHistoryTasks(@QueryMap HashMap<String,String> map);

    @POST("auth")
    Call<UserDTO> userLogin(@Body JSONObject body);
}

使用类Retrofit生成接口CyyHttpService的实现

CyyHttpService service = retrofit.create(CyyHttpService.class);
Call<ResponseBody<String>> total = service.getTotal("token");

//同步
total.execute();

//异步
total.enqueue(new Callback<ResponseBody<String>>() {
    @Override
    public void onResponse(Call<ResponseBody<String>> call,    
                    Response<ResponseBody<String>> response) {
    }

    @Override
    public void onFailure(Call<ResponseBody<String>> call, Throwable t) {
    }
});

//取消正在执行的请求
total.cancel();

关于Call

Call是Retrofit中重要的一个概念,代表被封装成单个请求/响应的交互行为

通过调用Retrofit2的execute(同步)或者enqueue(异步)方法,发送请求到网络服务器,并返回一个响应(Response)。

  1. 独立的请求和响应模块
  2. 从响应处理分离出请求创建
  3. 每个实例只能使用一次。
  4. Call可以被克隆。
  5. 支持同步和异步方法。
  6. 能够被取消。

由于call只能使用一次,所以上面代码执行下来会得到如下异常:

java.lang.IllegalStateException: Already executed.

可以通过clone一份call,使其继续执行

Call<ResponseBody<String>> total2 = total.clone();
//异步
total.enqueue(new Callback<ResponseBody<String>>() {
    @Override
    public void onResponse(Call<ResponseBody<String>> call, Response<ResponseBody<String>> response) {
    }

    @Override
    public void onFailure(Call<ResponseBody<String>> call, Throwable t) {
    }
});

参数相关

固定参数查询

@GET("tasks?pageNo=1")
Call<PageDataDTO<HistoryTaskDTO>> getHistoryTasks();

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

// 请求头
// GET http://.../tasks?pageNo=1 HTTP/1.1

动态参数(Query)

@GET("tasks")
Call<PageDataDTO<HistoryTaskDTO>> getHistoryTasks(@Query("pageNo") int no);

// 方法调用
//service.getHistoryTasks(2);

// 请求头
// GET http://.../tasks?pageNo=2 HTTP/1.1

动态参数(QueryMap)

@GET("tasks")
Call<PageDataDTO<HistoryTaskDTO>> getHistoryTasks(@QueryMap Map<String,String> map);

//方法调用
HashMap<String,String> params = new HashMap<>();
params.put("pageNo", "1");
params.put("pageSize", "10");
service.getHistoryTasks(params);

// 请求头
// GET http://.../tasks?pageNo=1&pageSize=10 HTTP/1.1

固定头

@GET("tasks")
@Headers("Accept-Encoding: application/json")
Call<PageDataDTO<HistoryTaskDTO>> getHistoryTask();

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

// 请求头
// GET http://.../tasks HTTP/1.1
// Accept-Encoding: application/json

动态头

@GET("tasks")
Call<PageDataDTO<HistoryTaskDTO>> getHistoryTask(@Header("Location") String location);

// 方法调用
//service.getHistoryTask("china");

// 请求头
// GET http://.../tasks HTTP/1.1
// Location: china

路径替换

@GET("{token}/account/total/fetch")
Call<ResponseBody<String>> getTotal(@Path("token") String token);

//方法调用
//service.getTotal("fd88b2ff");

// 请求头
// GET http://.../fd88b2ff/account/total/fetch HTTP/1.1

POST请求(无BODY)

//POST请求无BODY
@POST("auth")
Call<UserDTO> userLogin();

POST请求(带BODY,)

//POST请求带BODY,其中的body对象将被Retrofit实例指定的转换器转换
@POST("auth")
Call<UserDTO> userLogin(@Body User user);

POST请求(表单传参,Field)

@FormUrlEncoded
@POST("auth")
Call<UserDTO> userLogin( @Field("username") String username);

POST请求(表单传参,FieldMap)

@FormUrlEncoded
@POST("auth")
Call<UserDTO> userLogin(@FieldMap Map<String, String> params);

//方法调用
HashMap<String,String> params = new HashMap<>();
        params.put("username", "15222222222");
        params.put("code", "123456");
service.userLogin(params);

动态URL

@FormUrlEncoded 
Call<UserDTO> getUserInfo(@Url String url);

版权声明:

本文标题:Retrofit2使用简介

作者:Rabtman

原始链接:https://rabtman.com/2016/07/16/retrofit2_use/

本文采用署名-非商业性使用-禁止演绎4.0进行许可。

非商业转载请保留以上信息。商业转载请联系作者本人。