您当前的位置: 首页 > 

郭梧悠

暂无认证

  • 0浏览

    0关注

    402博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Retrofit之Converter简单解析

郭梧悠 发布时间:2018-09-08 09:45:01 ,浏览量:0

《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 {
  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 responseBodyConverter(Type type,
        Annotation[] annotations, Retrofit retrofit) {
      return null;
    }

    //将未知数据转换成RequestBody的转换器
    public @Nullable Converter responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    //Gson的数据转换器
    TypeAdapter adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter(gson, adapter);
  }

responseBodyConverter方法需要根据type类型来返回一个对应的Gson的TypeAdapter对象交给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是怎么知道返回值数据的真实类型的呢? 我们知道java中一个对象是封装成Method对象的:

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

其实这个拿到的是一个Call类型的对象,是拿不到T具体的T对象的,为此 在ServiceMethod的createAdapter方法中对接口方法做了处理(详情见):

  private CallAdapter createCallAdapter() {
      //获取方法的放回值类型
      Type returnType = method.getGenericReturnType();
     
      Annotation[] annotations = method.getAnnotations();
      //将returnType 交给 一个CallAdapter
        return (CallAdapter) retrofit.callAdapter(returnType, annotations);
    
    }

上面的returnType已经辗转之后具体在Retrfoit中交给了ExecutorCallAdapterFactory,对ReturnType做了进一步的解析来获取真正的javaBean类型:

 //ExecutorCallAdapterFactory的get方法
  public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
  
    //获取真正的JavaBean类型,比如Call 则返回T的type对象 
    final Type responseType = Utils.getCallResponseType(returnType);
   
     return new CallAdapter converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        return (Converter) converter;
      }
    }

    //省略部分代码
  }

nextResponseBodyConverter方法做的核心工作就是遍历Converter.Factory的集合,然后调用Factory对象的responseBodyConverter,如果该方法的返回值不为null则确认匹配成功并立即终止循环。其实最最核心的匹配原则是根据returenType进行匹配一个conveter对象的。

Retrofit没有写类似的if-else这些硬编码来过滤需要哪个Converter,而是设计了一个工厂类,通过通过模式来完成Converter对象的创建。这点还是很牛叉的,因为通过我们只需要添加自己所需要的工厂类即可,可插拔性极强。事实上Retrofit自己提供了好多Converter.Factory的实现,如下图,第一个就是我们熟悉的GsonConverterFactory对象的实现: 在这里插入图片描述

简单的用一个图片来作为本篇博文的总结: 在这里插入图片描述 到此为止Retrofit对服务器返回的数据转换内部原理就讲解完毕,如果不对的地方,欢迎批评指正。 在此遗留一个问题,前面说过Converter.Factory添加了一个默认的BuiltInConverters对象,这个对象的作用是神马呢?后面在分析。

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

关注
打赏
1663674776
查看更多评论
立即登录/注册

微信扫码登录

0.8785s