您当前的位置: 首页 > 
  • 0浏览

    0关注

    674博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

开源框架解读--Retrofit 2.0解析

沙漠一只雕得儿得儿 发布时间:2020-09-06 12:10:03 ,浏览量:0

Retrofit调用流程图和使用到的设计模式

第二篇:Retrofit调用流程图和使用到的设计模式 - wlrhnh - 博客园

Retrofit分析-漂亮的解耦套路

Retrofit分析-漂亮的解耦套路 - 简书

从架构角度看Retrofit的作用、原理和启示

从架构角度看Retrofit的作用、原理和启示 - 简书

Retrofit实现原理——函数解析、网络请求和数据转换

在前面分析中,我们知道了Retrofit的整体工作流程,就是Retrofit用动态代理生成Call网络请求对象,在这个过程中,用适配器把Retrofit底层的retrofit2.Call对象转换为INetApiService中定义的Call网络请求对象(如Flowable)。

问题是,Retrofit具体是如何知道了INetApiService中定义的Call网络请求对象,如何实现网络请求,以及如何执行的数据转换呢?

具体过程如下; 首先,根据INetApiService中定义的函数,解析函数,得到函数的具体定义,并生成对应的ServiceMethod(会提前从缓存中获取,没有了才创建,提高效率)。

然后,根据这个ServiceMethod,实现一个OkHttpCall的Call对象,负责在Retrofit底层实现网络访问。

其中,在网络访问返回了网络数据时,根据ServiceMethod实现数据转换。 最后,利用上一小节中匹配的适配器,把OkHttpCall对象转换为INetApiService要求的Call网络请求对象。 

所以,我们要了解的就是函数解析、网络请求和数据转换这三个动作,至于最后的适配转换,在上一节中已经分析过了。

1. 函数解析 在接口函数里,用注解描述了输入参数,用Java对象定义了返回值类型,所以对输入参数和返回值,ServiceMethod采取了不同的方式去处理。输入参数 输入参数是用来描述url的,它的处理相对简单,ServiceMethod会根据反射得到的Method,取得Annotation注解信息,这些注解是Retrofit自己预定义好的(retrofit2.http.*),ServiceMethod根据预先的定义,直接判断注解所属的逻辑分支,在有网络请求时分情况进行处理,就能得到目标url,http请求头等数据。返回值 返回值是需要用CallAdapter去适配的,所以核心在于生成对应的CallAdapter。 在Retrofit生成Call网络工作对象时,她通过动态代理获取到了接口函数的Method定义,从这个Method中可以获取函数定义的返回对象类型,由于这个转换是需要CallAdapterFactory生产CallAdapter对象去实现,而Retrofit事先并不知道要使用哪个Factory,所以她是遍历所有的CallAdapterFactory,根据目标函数的返回值类型,让每个Factory都去尝试生产一个CallAdapter,哪个成功就用哪个。

2. 网络请求 OkHttpCall继承的retrofit2.Call接口是为了依赖倒置解耦的,真正的网络请求是由OkHttpCall内部引用的okhttp3.call处理的,这个okhttp3.call是 借道ServiceMethod获取的Retrofit中的callFactory,也就是Retrofit中的OkHttpClient。

整个引用链条是这样的: OkHttpCall--okhttp3.call --> ServiceMethod--callFactory --> Retrofit.build()--callFactory//(如未扩展赋值)new OkHttpClient(); --> Retrofit.Builder().client(mClient)//(可能有扩展赋值)扩展过的OkHttpClient

最终的网络请求是由OkHttpCall调用OkHttpClient发出的,调用和回调等过程,也就是在OkHttpCall中处理的。

网络请求的生成过程中,为了使用接口函数中定义的参数,OkHttpCall会调用ServiceMethod来生成Request请求对象,再交给OkHttpCall去处理。

3. 数据转换 因为回调是在OkHttpCall中处理的,所以对回调数据的转换也在OkHttpCall中触发,为了符合接口函数中定义的返回数据类型,OkHttpCall会调用ServiceMethod来转换Response返回数据对象。

OkHttpCall对返回的网络数据,会调用一个serviceMethod.toResponse(ResponseBody body)函数,函数中执行的是:

  R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }

这个函数可以把原始的okhttp3. ResponseBody数据转换为INetApiService接口中要求的数据类型(如BizEntity类型)。 从代码可以看出,实现数据转换的核心对象其实是responseConverter,这个Converter实际上要依次经过Retrofit的建造和ServiceMethod的建造后,才能确定下来的。

Retrofit建造时添加数据转换工厂 Retrofit里有converterFactries列表,这是在我们初始化Retrofit实例时添加的

//retrofit对象
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(Config.DOMAIN)
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(YourConverterFactory.create())//添加自定义Converter
.build();

ServiceMethod建造时设定数据转换器 ServiceMethod在建造时,就已经确定了对应的是INetApiService中的哪个函数,所以需要明确设定自己的Converter转换对象

  public ServiceMethod build() {
      ...
      responseConverter = createResponseConverter();
      ...
  }

这需要调用Retrofit

    private Converter createResponseConverter() {
      ...
      retrofit.responseBodyConverter(responseType, annotations);
    }

Retrofit会在自己的转换器工厂列表中遍历每个ConverterFactory,尝试根据ServiceMethod所对应的目标数据类型,找到Converter数据转换类

    for (int i = start, count = converterFactories.size(); i < count; i++) {
      Converter converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter) converter;
      }
    }

以Gson转换为例,GsonConverterFactory会通过getAdapter来尝试匹配目标数据类型:

public  TypeAdapter getAdapter(TypeToken type) {...}

如果可以匹配,那么前面调用serviceMethod.toResponse(ResponseBody body)函数时,会调用

  R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }

在调用这段代码时,其实就是调用了Gson中最终执行数据转换的代码:

  @Override public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      return adapter.read(jsonReader);
    } finally {
      value.close();
    }
  }

总结来说,Retrofit在类的单一职责方面分隔的很好,OkHttpCall类只负责网络交互,凡是需要知道函数定义的,都交给ServiceMethod类去处理,而ServiceMethod类对使用者不公开,因为Retrofit是个外观模式,而所有需要扩展的都在Retrofit的建造者中实现,他们的分工大概是这样的:

Android Retrofit 2.0 的详细 使用攻略(含实例讲解)

Carson带你学Android:网络请求库Retrofit使用教程(含实例讲解) - 简书

Retrofit源码解析流程图

只有如下一张图

Retrofit源码解析流程图_ForgetSky的博客-CSDN博客

Retrofit2之CallAdapter和Converter

Retrofit2之CallAdapter和Converter_weixin_34274029的博客-CSDN博客

需要搞明白如下问题:

  1. CallAdapterFactory是如何起作用的?
  2. ConverterFactory是如何起作用的?
定义StringCallAdapterFactoryStringCallAdapter
public class StringCallAdapterFactory extends CallAdapter.Factory {
    @Nullable
    @Override
    public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        if(returnType == String.class)
            return new StringCallAdapter();
    	 return null;
    }
 
    class StringCallAdapter implements CallAdapter{
        @Override
        public Type responseType() {
            return String.class;
        }
 
        @Override
        public String adapt(Call call) {
            try {
                return call.execute().body();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "";
        }
    }
}
 
复制代码
定义StringConverterFactoryStringConverter
public class StringConverterFactory extends Converter.Factory {
    @Nullable
    @Override
    public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        if (type == String.class) {
            return new StringConverter();
        }
        return null;
    }
 
    class StringConverter implements Converter {
 
        @Override
        public String convert(ResponseBody value) throws IOException {
            return value.string();
        }
    }
}
复制代码

通过自定义CallAdapter和Convert,

首先会执行到Adapter的responseType,返回为我们想要的自定义的String.class

converter通过CallAdapter的返回值String.class,完成后续的请求response结果的转换。

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

微信扫码登录

0.0398s