Retrofit之Converter简单解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chunqiuwei/article/details/82526077

Retrofit源码解析之请求流程概述》简单的对Retrofit的请求流程做了梳理:从该篇文章中我们知道Retrofit是通过Convert来完成数据解析转换的:

//ServiceMethod的方法
R toResponse(ResponseBody body) throws IOException {
    //Converter对象 
    return responseConverter.convert(body);
  }

本文就以Gson作为数据转换类简单的介绍Converter是怎么工作的。
So,让我们开车吧!咳,让我们开始吧。

Retrofit在内部帮我们将服务器返回的数据进行了解析,数据解析的目的无非就是将一种数据源转换成另外一种数据类型,所以Retrofit将此行为抽象成了一个接口:

//F源数据,T解析后返回的数据类型
public interface Converter<F, T> {
  T convert(F value) throws IOException;
}

常规情况下我们只对服务器返回的数据源解析成我们的需要的数据就可以了,在Okhttp中服务器返回的数据源就是对ResponseBody。所以我们的目标就是对ResponseBody进行解析:

T convert(ResponseBody value){
  //do convert and return t
}

其实Retrofit考虑的远远比我们的多,不仅可以对ResponseBody进行转换,也可以对RequestBody进行转换;具体其内部提供了一个Convert.Factory:

abstract class Factory {
    //对ResponseBody进行数据转换的转换器
    public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
        Annotation[] annotations, Retrofit retrofit) {
      return null;
    }

    //将未知数据转换成RequestBody的转换器
    public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
      return null;
    }

    //将未知数据转换成String类型的数据转换器
    public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }
}

我们知道,如果要Retrofit要使用Gson作为数据转换器的话,在初始化Retrofit的时候需要添加这么一个代码:

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.xxx.xxx")  
               .addConverterFactory(GsonConverterFactory.create()) //添加Gson
                .build();

此篇博文的主旨就是看看这玩意内部的具体原理.,不用说GsonConvertFactory实现了Convert.Factory。其create方法如下:

  public static GsonConverterFactory create() {
    return create(new Gson());
  }

  public static GsonConverterFactory create(Gson gson) {
    return new GsonConverterFactory(gson);
  }

  class GsonConverterFactory extends Converter.Factory{
     private final Gson gson;

     private GsonConverterFactory(Gson gson) {
       this.gson = gson;
      }
  }

所以我们来看看GsonConverterFactory 是怎么对ResponseBody 进行JavaBean的转换的吧:

 public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    //Gson的数据转换器
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }

需要根据type类型来返回一个对应的Gson的TypeAdapter对象,那么是如何获取类型Type的呢?我们知道java中一个对象是封装成Method对象的,根据这method我们就可以拿到方法的返回值了,其实就是用下面代码:

 //根据Method对象获取对应method的返回值类型
 Type returnType = method.getGenericReturnType();

根据这个TypeAdapter对象responseBodyConverter返回了GsonResponseBodyConverter这个转换器,进入其convet方法看看:

public T convert(ResponseBody value) throws IOException {
    //拿到ResponseBody的数据流
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
     //Gson将数据转换成JavaBen
      return adapter.read(jsonReader);

  }

还是很简单的逻辑:
1、拿到ResopnseBody的真实数据流
2、交给Gson的JsonReader进行处理
3、调用Adapter的read方法返回对应的JavaBean
关于TypeAdapter的详细使用,可以参考博主的《Gson源码解析

到此为止Retrofit对服务器返回的数据转换内部原理就讲解完毕,如果不对的地方,欢迎批评指正。

根据《Retrofit源码解析之请求流程概述》我们知道Retrofit通过OkhttpCall来完成同步或者异步请求,那么OkhttpCall的execute和enqueue方法是什么时候开始执行的呢?答案在下一篇博客

猜你喜欢

转载自blog.csdn.net/chunqiuwei/article/details/82526077