Retrofit2学习笔记-1

来源:互联网 发布:驱动精灵知乎 编辑:程序博客网 时间:2024/06/05 22:33

什么是Retrofit2

Retrofit是一个给Android和Java用的类型安全的HTTP客户端,它将网络请求封装成接口,并采用注解的形式声明请求,由Retrofit自动生成接口实现对象给开发者调用。

Retofit2的入门
1. 引用Retrofit2
Gradle引用
compile 'com.squareup.retrofit2:retrofit:2.1.0'
Maven引用

<dependency>  <groupId>com.squareup.retrofit2</groupId>  <artifactId>retrofit</artifactId>  <version>2.1.0</version>  </dependency>
  1. Retrofit2入门
    接下来我们一步一步的学习使用Retrofit2的使用。
    • 创建Retrofit2实例
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://wthrcdn.etouch.cn/").build();

创建Retrofit2实例时需要通过Retrofit.Builder方法,并调用baseUrl方法设置根URL。Retrofit2的baseUlr必须以/结束,不然会抛出一个IllegalArgumentException。

  • 定义一个和HTTP的API对应的接口
    /** * 天气服务     */    public interface WeatherService {        @GET("weather_mini")        Call<WeatherBean> getWeatherInfo(@Query("city") String city);    }
  • 生成网络请求接口的对象
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://wthrcdn.etouch.cn/").addConverterFactory(GsonConverterFactory.create(gson))//这块定义了一个转换器,之后会讲解.build();WeatherService service = retrofit.create(WeatherService.class);
  • 调用实现的方法来进行同步或异步的HTTP请求
Call<WeatherBean> call1 = service.getWeatherInfo("沈阳");//异步请求call1.enqueue(new Callback<WeatherBean>() {    @Override    public void onResponse(Call<WeatherBean> call, Response<WeatherBean> response) {        Log.d("Retrofit2Example", response.body().getDesc());    }    @Override    public void onFailure(Call<WeatherBean> call, Throwable t) {        Log.d("Retrofit2Example", t.getMessage());    }});try {    //同步请求    Response<WeatherBean> response = call1.execute();    if (response.isSuccessful()) {         Log.d("Retrofit2Example", response.body().getDesc());           }} catch (IOException e) {             e.printStackTrace();}

以上就是一个非常简单的GET请求,可以看到通过Retrofit2的create()方法生成网络接口的实现对象,之后调用具体的接口调用方法会生成一个请求对应的Call对象,在这个时候请求并没有发送出去,接下来调用Call对象的enqueue或者execute方法实现异步和同步的网络请求。
1. 详细分析每一步
- Retrofit2对象的创建

 Retrofit retrofit = new Retrofit.Builder().baseUrl("http://wthrcdn.etouch.cn/").build();

可以看到我们可以使用Retrofit.Builder().build()这个方法创建一个Retrofit2对象,在创建的时候还可以使用baseUrl()方法为Retrofit2对象设置一个根路径。这块很好理解,那么我们再介绍一下Retrofit2对象创建的时候还可以做的一些操作。
1.首先介绍一下转换器,转换器顾名思义就是将服务端返回的Response进行转换。在默认情况下Retrofit只支持将HTTP的响应体转换换为ResponseBody。比如要用Gson解析的话就需要添加依赖并使用addConverterFactory方法设置转换器。

<!-- 引入gson -->compile 'com.squareup.retrofit2:converter-gson:2.0.2'
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd hh:mm:ss").create();Retrofit retrofit = new Retrofit.Builder().baseUrl("http://wthrcdn.etouch.cn/").addConverterFactory(GsonConverterFactory.create(gson)).build();

上面的代码首先创建了一个gson对象,之后再创建retrofit对象的时候使用addConverterFactory方法设置了转换器。经过这个设置之后呢我们在之后的请求中就可以使用泛型去作为请求体或者返回值了。

public class WeatherBean {    private String desc;    private int status;    private Data data;    public void setDesc(String desc) {        this.desc = desc;    }    public String getDesc() {        return this.desc;    }    public void setStatus(int status) {        this.status = status;    }    public int getStatus() {        return this.status;    }    public void setData(Data data) {        this.data = data;    }    public Data getData() {        return this.data;    }}

当我们设置了gson转换器之后服务端返回的json格式的字符串就会被转换成相应的对象了。当然如果你没有设置转换器的话这块的泛型就是默认的ResponseBody了。

    /** * 天气服务     */    public interface WeatherService {        @GET("weather_mini")        Call<ResponseBody> getWeatherInfo(@Query("city") String city);    }
  • 自定义Converter
    retrofit自带的转换器:
    • 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,String):com.squareup.retrofit2:converter-scalars
      如果自带的转换器不能满足我们的需要,这个时候我们就需要自定义一个转换器Converter了。
public interface Converter<F, T> { // 实现从 F(rom) 到 T(o)的转换 T convert(F value) throws IOException; // 用于向Retrofit提供相应Converter的工厂 abstract class Factory { // 这里创建从ResponseBody向其它类型的Converter,如果不能转换返回null // 主要用于对响应体的处理 public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return null; } // 在这里创建 从自定类型到RequestBody的Converter,不能处理就返回null, // 主要用于对Part、PartMap、Body注解的处理public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { return null; }// 这里用于对Field、FieldMap、Header、Path、Query、QueryMap注解的处理 // Retrfofit对于上面的几个注解默认使用的是调用toString方法 public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return null; } }}

比如我们要定义Call<ResponseBody> 转换为Call<String>的转换器,那么对应的F和T则分别对应ResponseBodyString,我们定义一个StringConverter并实现Converter接口。

public static class StringConverter implements Converter<ResponseBody, String> {           public static final StringConverter INSTANCE = new StringConverter();           @Override           public String convert(ResponseBody value)throws IOException {                 return value.string();            }}

还需要一个Factory来向Retrofit注册StringConverter。

public static class StringConverterFactory extends Converter.Factory {           public static final StringConverterFactory INSTANCE = new StringConverterFactory();           public static StringConverterFactory create() {                return INSTANCE;            }            // 我们只关实现从ResponseBody 到 String 的转换,所以其它方法可不覆盖            @Override            public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {                 if (type == String.class) {                      return StringConverter.INSTANCE;                 }                 //其它类型我们不处理,返回null就行                 return null;            }}

好了,之后我们再使用Retrofit.Builder.addConverterFactory向Retrofit注册我们StringConverterFactory

Retrofit retrofit = new Retrofit.Builder().baseUrl("http://wthrcdn.etouch.cn/") // 如是有Gson这类的Converter 一定要放在其它前面.addConverterFactory(StringConverterFactory.create()).addConverterFactory(GsonConverterFactory.create()).build();

这里addConverterFactory是有先后顺序的,如果有多个ConverterFactory都支持同一种类型,那么就是只有第一个才会被使用,而GsonConverterFactory是不判断是否支持的,所以这里交换顺序还会有一个异常抛出,原因是类型不匹配。现在只要返回值类型的泛型参数是String就会由我们的StringConverter处理。

0 0
原创粉丝点击