通过源码,分析Retrofit2的整体执行流程

RetrofitAndroid应用层最为广泛的网络请求框架之一。
它通过动态代理、工厂模式、Builder模式等设计模式,对Okhttp进行了巧妙封装。
本文,将对Retrofit2 源码进行分析。若无特殊说明,源码api为2.7.2

一.动态代理

在使用Retrofit 时,我们先定义一个接口,然后通过调用retrofit.create方法,得到一个接口的实例,最后通过该实例执行我们的操作。

Retrofit在设计过程中,有一个很重要的知识点,动态代理.

在正式学习Retrofit源码之前,先对Java中的动态代理进行了解。

先定义一个接口:

代码片1
public interface ITest {
    
    

    @GET("/test")
    public void add(int a, int b);
}

通过动态代码的代码如下:

代码片2
   ITest iTest = (ITest) Proxy.newProxyInstance(ITest.class.getClassLoader(),
                new Class<?>[]{
    
    ITest.class}, new InvocationHandler() {
    
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
                Integer a = (Integer) args[0];
                Integer b = (Integer) args[1];
                System.out.println("方法名:" + method.getName());
                System.out.println("参数:" + a + " , " + b);

                GET get = method.getAnnotation(GET.class);
                System.out.println("注解:" + get.value());
                return null;
            }
        });

   iTest.add(3, 5);

输出结果如下:

I/System.out: 方法名:add
I/System.out: 参数:3 , 5
I/System.out: 注解:/test

可以看到通过 Proxy.newProxyInstance 产生的代理类,当调用接口的任何方法时,都会调用 Proxy#InvocationHandler 方法,在这个方法中可以拿到传入的参数、注解等。

二.Retrofit源码分析

代码片3
       Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .addConverterFactory(GsonConverterFactory.create(mGson))
                .build();

        GitHubService service = retrofit.create(GitHubService.class);
        Call<List<Repo>> call = service.listRepos("gaolhjy");
        call.enqueue(new Callback<List<Repo>>() {
    
    
            @Override
            public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
    
    
                Log.e(TAG, "onResponse: " + "success");
            }

            @Override
            public void onFailure(Call<List<Repo>> call, Throwable t) {
    
    
                Log.e(TAG, "onResponse: " + "onFailure");
            }
        });

上述代码,是比较典型的使用Retrofit进行的网络请求的写法。

(一) Retrofit的创建过程

代码片4
Retrofit retrofit = new Retrofit.Builder()    //1.创建builder
      .baseUrl("https://api.github.com/")     //2.配置builder
      .build();                              //3、创建Retrofit实例

1.创建builder

代码片5
public static final class Builder {
    
    
   
    private final Platform platform;    //运行Retrofit的平台
    //省略部分代码
   
   //根据Platform构造
    Builder(Platform platform) {
    
    
      this.platform = platform;
    }

    public Builder() {
    
    
      this(Platform.get());
    }

    //根据另外一个Retrofit构造
    Builder(Retrofit retrofit) {
    
    
      platform = Platform.get();
      callFactory = retrofit.callFactory;
      baseUrl = retrofit.baseUrl;
      //省略部分代码
     }

okhttp一样,Retrofit的实例化也是采用builder模式。

我们使用了无参的构造函数来创建BuilderBuilder的无参构造函数首先通过Platform.get()获取了一个Platform实例赋值给了platform字段,前面提到过Retrofit是有Platform的概念,Retrofit支持javaAndroid平台。

我们来看一下Platform类.

代码片6
class Platform {
    
    
  
  //单例
  private static final Platform PLATFORM = findPlatform();
  
  //返回Platform 对象
  static Platform get() {
    
    
    return PLATFORM;
  }

  private static Platform findPlatform() {
    
    
    try {
    
    
      //android.os.Build这个类是Android独有的
      //这里要求JVM查找并加载Build.class对象
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
    
    
        //如果是Android平台,创建一个Android实例返回,Android继承自Platform
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    
    
      //找不到android.os.Build,会抛出异常,捕捉,继续执行
    }
    //返回默认Platform实例,并传hasJava8Types为true
    return new Platform(true);
  }

  private final boolean hasJava8Types;

  Platform(boolean hasJava8Types) {
    
    
    this.hasJava8Types = hasJava8Types;
  }

  //返回默认的线程切换执行器
  @Nullable Executor defaultCallbackExecutor() {
    
    
    return null;
  }

  //返回默认的网络请求适配器工厂
  List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
      @Nullable Executor callbackExecutor) {
    
    
    DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
    return hasJava8Types
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
  }

  int defaultCallAdapterFactoriesSize() {
    
    
    return hasJava8Types ? 2 : 1;
  }

  List<? extends Converter.Factory> defaultConverterFactories() {
    
    
    return hasJava8Types
        ? singletonList(OptionalConverterFactory.INSTANCE)
        : emptyList();
  }

  int defaultConverterFactoriesSize() {
    
    
    return hasJava8Types ? 1 : 0;
  }

  boolean isDefaultMethod(Method method) {
    
    
    return hasJava8Types && method.isDefault();
  }

  @Nullable Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object,
      @Nullable Object... args) throws Throwable {
    
    
    // Because the service interface might not be public, we need to use a MethodHandle lookup
    // that ignores the visibility of the declaringClass.
    Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
    constructor.setAccessible(true);
    return constructor.newInstance(declaringClass, -1 /* trusted */)
        .unreflectSpecial(method, declaringClass)
        .bindTo(object)
        .invokeWithArguments(args);
  }

  static final class Android extends Platform {
    
    
    Android() {
    
    
      super(Build.VERSION.SDK_INT >= 24);
    }

    @Override public Executor defaultCallbackExecutor() {
    
    
      return new MainThreadExecutor();
    }
    
    //线程切换执行器
    // MainThreadExecutor,它是一个Executor,它的execute方法的实现就是简单通过Handler把任务Runnable切换回主线程执行,就是说,线程池会把每一个线程提交的任务都切回主线程执行
    
    static class MainThreadExecutor implements Executor {
    
    
       // 构造Handler时通过Looper.getMainLooper()来构造
       // 所以Handler的消息都会执行在主线程
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
    
    
        handler.post(r);
      }
    }
  }
}

2.配置builder

Retrofit.class

 public static final class Builder {
    
    
    private final Platform platform;    //Retrofit运行的平台
    private @Nullable okhttp3.Call.Factory callFactory;  //网络请求执行器工厂,用创建网络请求执行器实例,来自okhttp, 不是Retrofit中的那个Call
    private @Nullable HttpUrl baseUrl;   //网络请求的Url地址
    private final List<Converter.Factory> converterFactories = new ArrayList<>();  //数据转化器工厂列表
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();  //网络请求工厂列表
    private @Nullable Executor callbackExecutor;   //线程切换执行器
    private boolean validateEagerly;   //标志位,是否提前对serviceMethod进行缓存(在创建Api接口实例会讲到)

   ....
   //省略创建builder的代码
 
   //我们传入的String类型的Url,最终还是会解析成HttpUrl类型,它是Retrofit中url的代表
    public Builder baseUrl(URL baseUrl) {
    
    
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      return baseUrl(HttpUrl.get(baseUrl.toString()));
    }

    
    public Builder baseUrl(String baseUrl) {
    
    
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      return baseUrl(HttpUrl.get(baseUrl));
    }

   
    public Builder baseUrl(HttpUrl baseUrl) {
    
    
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      List<String> pathSegments = baseUrl.pathSegments();
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
    
    
        // baseUrl最后一定要接一个
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }

   //把converFactory添加到数据转化器工厂列表中
    public Builder addConverterFactory(Converter.Factory factory) {
    
    
      converterFactories.add(Objects.requireNonNull(factory, "factory == null"));   //converterFactories是一个ArrayList集合
      return this;
    }

    //把CallAdapterFactory添加到网络请求适配器工厂列表中
    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
    
    
      callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null"));
      return this;
    }

    //从service方法返回Call时,在其上调用Callback方法的执行程序。
    //注意:executor不用于addCallAdapterFactory自定义方法返回类型
    public Builder callbackExecutor(Executor executor) {
    
    
      this.callbackExecutor = Objects.requireNonNull(executor, "executor == null");
      return this;
    }

   //获取网络请求适配器工厂列表
    public List<CallAdapter.Factory> callAdapterFactories() {
    
    
      return this.callAdapterFactories;
    }

    //获取数据转化器工厂列表
    public List<Converter.Factory> converterFactories() {
    
    
      return this.converterFactories;
    }

    //修改validateEagerly标志位
    public Builder validateEagerly(boolean validateEagerly) {
    
    
      this.validateEagerly = validateEagerly;
      return this;
    }

    //省略代码. 第三部分 创建Retrofit实例 会讲解
  }

Builder中所有的字段都贴出来了,方法只贴了几个常用的出来,我们调用Builder的相应方法,就是在为Builder的相应字段赋值,很简单。这也是Builder模式的优势。

其中需要注意的是,当我们添加ConverterFactoryCallAdapterFactory时,它们都是添加到各自的列表中,这也说明Retrofit添加ConverterCallAdapter是可以同时存在多个的.这是为什么呢?这是因为Retrofit允许为Api接口里面定义的每一个方法都定义对应的ConverterCallAdapter,每当我们调用Api的某个接口方法时,Retrofit都会遍历网络请求适配器工厂列表callAdapterFactories,把方法的返回值returnType和注解信息annotations传进每个Factoryget方法中,看某个Factory是否愿意处理这个方法,为这个方法创建对应CallAdapter实例;同理,当Retrofit解析某个Api接口方法的网络请求数据时,它同样会遍历数据转化器工厂列表converterFactories,把方法的相关信息传给FactoryresponseBodyConverterrequestBodyConverter方法,看某个Factory是否愿意处理这个方法,为这个方法创建对应ResponseBodyBodyConverterRequestBodyConverter实例,这两个过程在待会的源码分析都会体现到。

3.创建Retrofit实例

Retrofit.class

 public Retrofit build() {
    
    
      if (baseUrl == null) {
    
    
        throw new IllegalStateException("Base URL required.");
      }

      //配置网络请求执行器工厂callFactory
      okhttp3.Call.Factory callFactory = this.callFactory;
      //如果没有指定,使用默认的
      if (callFactory == null) {
    
    
         //默认指定为OkHttpClient, OkHttpClient实现了Call.Factory接口,OkHttpClient和Call都是来自okhttp的
        callFactory = new OkHttpClient();
      }
      //配置线程切换执行器callbackExecutor
      Executor callbackExecutor = this.callbackExecutor;
      //如果没有指定,使用默认的
      if (callbackExecutor == null) {
    
    
         //默认指定为运行平台默认的线程切换执行器
         //在Android中,defaultCallbackExecutor方法的返回值就是MainThreadExecutor实例
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      //配置网络请求适配器工厂列表
        //添加用户指定的网络请求适配器工厂列表
        List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
        //添加运行平台默认的网络请适配器工厂到列表中
        //在Android中,defaultCallAdapterFactory方法返回值就是ExecutorCallAdapterFactory实例,并把MainThreadExecutor实例传进方法,所以ExecutorCallAdapterFactory持有MainThreadExecutor实例(回去看构造Builder阶段)
        callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      //配置数据转化器工厂列表
        List<Converter.Factory> converterFactories =
            new ArrayList<>(1 + this.converterFactories.size());
	   //添加Retrofit默认的数据转化器工厂BuiltInConverters
        converterFactories.add(new BuiltInConverters());
        //添加用户指定的数据转化器工厂列表
        converterFactories.addAll(this.converterFactories);


      //创建一个Retrofit实例返回,并把上面的配置好的字段传进构造
      //这些字段和Retrofit中相应的字段同名,unmodifiableList就是创建一个不可修改的列表
      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }

build方法中把没有在配置Builder阶段中赋值的字段指定了默认值,然后把网络请求Url地址baseUrl、网络请求执行器工厂callFactory、线程切换执行器callbackExecutor、网络请求适配器工厂列表callAdapterFactories、数据转化器工厂列表converterFactories、标志位validateEagerly这六件套传进了Retrofit的构造,创建一个Retrofit实例返回。

其中要注意的是,按照添加顺序,工厂列表的优先级为:用户指定的网络请适配器工厂列表 > 运行平台默认的网络请求适配器工厂;Retrofit默认的数据转化器工厂 > 用户指定的数据转化器工厂列表。在遍历这些列表时是从前往后遍历的,越靠前的越先被访问。

4.小结

通过创建builder、配置builder、创建Retrofit这三步后,指定了Retrofit的运行平台、配置好了Retrofit网络请求Url地址、网络请求执行器工厂、线程切换执行器、网络请求适配器工厂列表、数据转化器工厂列表等字段,并创建了一个Retrofit实例。

(二)创建Api接口实例

 GitHubService service = retrofit.create(GitHubService.class);

Retrofitcreate方法如下:

Retrofit.class

代码片8
// 泛型T就是GithubService接口
public <T> T create(final Class<T> service) {
    
    
    validateServiceInterface(service);     //验证服务接口
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] {
    
     service },
        new InvocationHandler() {
    
    
          private final Platform platform = Platform.get();
          private final Object[] emptyArgs = new Object[0];

          @Override public @Nullable Object invoke(Object proxy, Method method,
              @Nullable Object[] args) throws Throwable {
    
    
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
    
    
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
    
    
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);  //重点分析1
          }
        });
  }

整体结构为 Proxy.newProxyInstance 即动态代理。 关于动态代理的知识,在 一.动态代理 中已经学习。

上述代码整体上看,就是传入什么类(比如GitHubService.class),经过动态代理之后,返回 GitHubService.class.

0.小结

当我们调用Retrofitcreate方法后,它返回了一个代理对象实例。

这个代理对象实现了create方法传进去的接口,接下来当我们调用Api接口方法时,就是在调用代理对象的同名方法,这个方法的处理逻辑就会委托给InvocationHandler实例的invoke方法执行。使用了动态代理之后的好处是:我们可以把网络请求的参数都集中在invoke方法中处理,而不需要为某一个接口定义一个实现类,这样降低了实现的难度。

1. loadServiceMethod方法

代码片9

private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();

ServiceMethod<?> loadServiceMethod(Method method) {
    
    
    //从serviceMethodCache根据方法method获取ServiceMethod
    ServiceMethod<?> result = serviceMethodCache.get(method);
    //如果获取得到就直接返回
    if (result != null) return result;

    //如果获取不到就为这个method创建一个ServiceMethod
    //上锁,所以创建的ServiceMethod是一个单例
    synchronized (serviceMethodCache) {
    
    
      result = serviceMethodCache.get(method);
      if (result == null) {
    
    
        //为method创建一个ServiceMethod
        result = ServiceMethod.parseAnnotations(this, method);    //parseAnnotations的中文意思是解析注解(重点分析2)
         //然后以方法method为键,ServiceMethod为值,放入serviceMethodCache(map集合)缓存起来
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

(三)发起网络请求(异步)

代码片10
    call.enqueue(new Callback<List<Repo>>() {
    
    
            @Override
            public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
    
    
                Log.e(TAG, "onResponse: " + "success");
            }

            @Override
            public void onFailure(Call<List<Repo>> call, Throwable t) {
    
    
                Log.e(TAG, "onResponse: " + "onFailure");
            }
        });

异步请求需要把结果通过Callback回调给上层.

call是一个接口, 它的实现类通过搜索后发现有且只有2个:

  1. OkHttpCall.class
final class OkHttpCall<T> implements Call<T>
  1. DefaultCallAdapterFactory#ExecutorCallbackCall
 static final class ExecutorCallbackCall<T> implements Call<T> {
    
    

到底是哪一个呢?思路陷入了僵局。

我们回过头看代码片8第12行代码 loadServiceMethod(method).invoke,看看调用invoke方法是怎么样的.

代码如下:

代码片11
abstract class ServiceMethod<T> {
    
    
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    
    
    //省略部分代码
    ....
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract @Nullable T invoke(Object[] args);
}

这是一个抽象方法, ServiceMethod返回值为 HttpServiceMethod.parseAnnotations

HttpServiceMethod.parseAnnotations 源码进去看,

代码片12
HttpServiceMethod<ResponseT, ReturnT> parseAnnotations

结合代码片8、代码片11、代码片12, 综合看:

loadServiceMethod(method).invoke 其实转移到了HttpServiceMethod类的invoke方法了.

那我们点进去看一下:

HttpServiceMethod.class

代码片13
 @Override final @Nullable ReturnT invoke(Object[] args) {
    
    
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }

在这里,果然看到了Call的实现类. 即OkhttpCall.

也就是说代码片10中的 call.enqueue 实际上调用的是OkhttpCallenqueue方法.

代码片14
 @Override public void enqueue(final Callback<T> callback) {
    
    
    Objects.requireNonNull(callback, "callback == null");
     
    //来自Okhttp的Call
    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
    
    
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
    
    
        try {
    
    
          //第一次发起网络请求,创建Okhttp的Call
          call = rawCall = createRawCall();
        } catch (Throwable t) {
    
    
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
    
    
      //通过callback把错误回调出去
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
    
    
      call.cancel();
    }

    //调用Okhttp的Call的enqueue方法发起异步请求
    //传入的是Okhttp的Callback
    call.enqueue(new okhttp3.Callback() {
    
    
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
    
    
        Response<T> response;
        try {
    
    
          //调用parseResponse方法把Okhttp的Response解析成Retrofit的Response
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
    
    
          throwIfFatal(e);
          callFailure(e);
          return;
        }

        //通过callback把结果回调出去
        try {
    
    
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
    
    
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }
      
      //Okhttp的错误回调
      @Override public void onFailure(okhttp3.Call call, IOException e) {
    
    
        callFailure(e);
      }

      private void callFailure(Throwable e) {
    
    
        try {
    
    
          //通过callback把错误回调出去
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
    
    
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }
    });
  }

OkhttpCallenqueue方法大体分为3步:

  1. 获取OkhttpCall实例,赋值给临时变量call
    ​ 1.1 如果是第一次发起网络请求,就调用createRawCall方法就创建来自OkhttpCall,赋值给临时变量call和成员变量rawCall;
    ​ 1.2 如果不是第一次发起网络请求,就把上次的rawCall实例赋值给临时变量call
  2. 调用OkhttpCallenqueue方法发起异步请求;
  3. 当网络请求结果正确返回时,用parseResponse方法把OkhttpResponse解析成RetrofitResponse

2.小结

以异步为例,Retrofit通过ExecutorCallbackCallenqueue发起的网络请求,最终会通过OKhttpCallenqueue方法来发起网络请求.

OkhttpCallenqueue方法中,首先会调用创建一个来自OkhttpCall实例,然后通过这个OkhttpCall实例的enqueue方法来发起异步请求,当网络请求结果OkhttpResponse返回时,调用parseResponse方法解析Response,parseResponse方法里面还会调用ServiceMethodtoResponse方法通过Converter实例的converter方法把ResponseBody转化为我们想要的数据。不同的数据转化有不同的实现,在Retrofit的默认实现中,它就是直接返回OkhttpResponseBody,最后把这个转化后的body和原始的OkhttpResponse一并封装成RetrofitResponse返回,最后把parseResponse方法返回的Response通过callback回调出去,这是ExecutorCallbackCall收到回调,通过线程切换执行器callbackExecutor,切换到主线程执行callback回调,一次异步请求就完成。

同步请求也是大同小异,只是少了一个回调。这里就不再分析。

三.几点补充

关于Retrofit的源码中,需要补充说明CallAdapterConverter。这也是Retrofit能在众多网络请求框架中脱颖而出深受欢迎的原因。

1.CallAdapter

网络请求适配器,用于把默认的网络请求执行器的调用形式,适配成在不同平台下的网络请求执行器的调用形式,CallAdapter的接口如下:

public interface CallAdapter<R, T> {
    
    
 
  //返回响应body转换为Java对象时使用的类型
  //例如Call<ResponseBody>, Type就是ResponseBody,Type是来自java.lang.reflect包的
  Type responseType();
  
  //把Call<R>适配成T类型,就是将Retrofit的Call类型转为另外一个类型的Call
  T adapt(Call<R> call);
  
  //用于创建CallAdapter实例,通过get方法
  abstract class Factory {
    
    
   
   //根据Api接口定义的方法的返回值和注解信息,创建一个CallAdapter实例返回,如果这个Factory不能处理这个方法的返回值和注解信息,返回null,
    //注意这里的returnType != 上面的responseType,例如Call<ResponseBody>,returnType的Type就是Call
    public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
        Retrofit retrofit);

    //返回ParameterizedType的上限,即泛型类型的上限
    //例如Call<? extends ResponseBody>, Type就是ResponseBody
    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
    
    
      return Utils.getParameterUpperBound(index, type);
    }

   //返回Type的原始类型
   //例如Type为Call<ResponseBody>,返回Call.class
    protected static Class<?> getRawType(Type type) {
    
    
      return Utils.getRawType(type);
    }
  }
}

CallAdapter接口很简单,只有2个方法responseTypeadapt方法,和一个Factory 类,其中Factory类的get方法可以获取一个CallAdapter实例,CallAdapterresponseType()方法可以获取T类型,这个Call就是我们在定义Api接口方法时方法的返回参数.CallAdapteradapt方法就是将传入的Call类型适配成另外一个我们期待的"Call",这里使用到了适配器模式.

适配器模式就是将两个因接口不兼容的类之间加上一个适配器,将一个类的接口变成客户端所期待的另外一个接口,从而使得他们工作在一起.至于怎么适配就需要看适配器中得adapt方法的实现.

Retrofit中,CallAdapter的默认实现是一个匿名类,可以通过CallAdapterFactory 获取,CallAdapterFactory的默认实现是ExecutorCallAdapterFactory,代码如下:

DefaultCallAdapterFactory .class

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
    
    
   //线程切换执行器(在Retrofit的创建过程中已讲解)
  private final @Nullable Executor callbackExecutor;

  DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    
    
    this.callbackExecutor = callbackExecutor;
  }

   //可以通过returnType获得responseType
   //因为returnType = Call<T>, 有了Call<T>, 当然可以获得Call中的T,而T就是responseType
  @Override public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    
    
    if (getRawType(returnType) != Call.class) {
    
    
      return null;
    }
    if (!(returnType instanceof ParameterizedType)) {
    
    
      throw new IllegalArgumentException(
          "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
    }
    final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

    final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
        ? null
        : callbackExecutor;

    return new CallAdapter<Object, Call<?>>() {
    
    
      //返回一个CallAdapter的匿名类
      @Override public Type responseType() {
    
    
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
    
    
        //默认CallAdapter的adapt方法返回
        return executor == null
             ? call
            : new ExecutorCallbackCall<>(executor, call);
      }
    };
  }

//网络请求执行器(在创建Api接口实例中中已经讲解)
  static final class ExecutorCallbackCall<T> implements Call<T> {
    
    
   // ....
  }
   
}

DefaultCallAdapterFactoryget方法中,new了一个CallAdapter返回,在CallAdapteradapt方法实现中,new了一个ExecutorCallbackCall返回,并把入参callexecutor传进了ExecutorCallbackCall的构造方法中,ExecutorCallbackCall就是一个实现了Call接口的类,还是一个Call,它就是Retrofit的默认网络请求执行器,可以看到Retrofit的默认的网络请求执行器适配,即adapt方法的默认实现就是用ExecutorCallbackCall包装传进来的Call,并返回ExecutorCallbackCall,这个传进来的Call就是Call的默认实现OkHttpCall,在Retrofit的构建过程中已经讲到。

既然CallAdapter能把默认的网络请求执行器的调用形式,适配成在不同平台下的网络请求执行器的调用形式,那么它支持哪些平台呢?这个在retrofit-adapter 模块中可以找到答案,如下:

在这里插入图片描述

Retrofit还支持guavajava8rxjavascala这四个平台(其中Android中最常见为java8rxjava)它们里面都各自实现了retrofit模块暴露出去的CallAdapter接口和CallAdapter接口中的Factory接口,在CallAdapteradapt方法中提供各自平台的适配,我们可以通过addCallAdapterFactory(Factory)来添加不同平台的CallAdapter工厂。

2.Converter

Converter为数据转换器. Converter把我们在Api中方法注解和参数转化为网络请求执行器需要的参数类型,和把网络请求返回的数据转为我们需要的数据类型.

Converter的接口如下:

public interface Converter<F, T> {
    
    
  //把F转化为T,用于在网络请求中实现对象的转化
  @Nullable T convert(F value) throws IOException;

  //通过Factory 的responseBodyConverter或requestBodyConverter方法获得Converter实例或null
  abstract class Factory {
    
    
 
  //返回一个处理网络请求响应(Response)的body的Converter实例,如果不能处理这些类型(type)和注解,返回null
    //这个Converter会把 ResponseBody 转化成 ?,这个ResponseBody是来自okhttp的
    //例如使用GsonConverter,?代表某个java对象类型
    public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
        Annotation[] annotations, Retrofit retrofit) {
    
    
      return null;
    }

   /**
     * Returns a {@link Converter} for converting {@code type} to an HTTP request body, or null if
     * {@code type} cannot be handled by this factory. This is used to create converters for types
     * specified by {@link Body @Body}, {@link Part @Part}, and {@link PartMap @PartMap}
     * values.
     */
   //返回一个处理网络请求(Request)的body的Converter实例,如果不能处理这些类型(type)和注解,返回null
    //这个Converter会把 ?转化成 RequestBody,这个RequestBody是来自okhttp的
    //这个Converter主要处理@Body、 @Part、@PartMap类型的注解
    public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    
    
      return null;
    }

     /**
     * Returns a {@link Converter} for converting {@code type} to a {@link String}, or null if
     * {@code type} cannot be handled by this factory. This is used to create converters for types
     * specified by {@link Field @Field}, {@link FieldMap @FieldMap} values,
     * {@link Header @Header}, {@link HeaderMap @HeaderMap}, {@link Path @Path},
     * {@link Query @Query}, and {@link QueryMap @QueryMap} values.
     */
    //返回一个处理网络请求(Request)的body的Converter实例
    //这个Converter会把 ?转化成 String
    //这个Converter主要处理@Field、@FieldMap、@Header、HeaderMap @HeaderMap、@Path、@Query、@QueryMap类型的注解
    public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
    
    
      return null;
    }

    //下面两个方法和上面CallAdapter的Factory中同名方法的意思一样
    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
    
    
      return Utils.getParameterUpperBound(index, type);
    }

    protected static Class<?> getRawType(Type type) {
    
    
      return Utils.getRawType(type);
    }
  }

Converter接口也很简单,只有一个convert方法,和一个Factory 类.

因为Converter要提供2个方向数据的转化,所以Factory 提供了2个方法分别用于获取不同方向的转化,其中**responseBodyConverter方法就是获得一个把网络返回的数据转化为我们需要的数据类型的Converter实例,而requestBodyConverter方法就是获得一个把我们在Api接口定义的方法注解和参数转化为网络请求的Converter实例,**那么要怎么转化呢?就要看Converterconvert方法的实现,convert方法把F类型 转化为 T类型,接下来我们看convert方法在Retrofit中的默认实现。

ConverterRetrofit的默认实现有五个,都是ConverterFactory的内部类,可通过ConverterFactory获得,ConverterFactory的默认实现是BuiltInConverters,如下:

final class BuiltInConverters extends Converter.Factory {
    
    
    
  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit Retrofit) {
    
    
    if (type == ResponseBody.class) {
    
    //支持ResponseBody类型的转化
      
      //如果是二进制流形式,就返回StreamingResponseBodyConverter实例
      //如果是字符流形式,就返回BufferingResponseBodyConverter实例
      return Utils.isAnnotationPresent(annotations, Streaming.class)
          ? StreamingResponseBodyConverter.INSTANCE
          : BufferingResponseBodyConverter.INSTANCE;
    }
    if (type == Void.class) {
    
    //支持Void类型的转化
        
      //返回VoidResponseBodyConverter实例
      return VoidResponseBodyConverter.INSTANCE;
    }
      
    //除了以上两种类型,其他类型都不支持,返回null
    return null;
  }

  @Override
  public Converter<?, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit Retrofit) {
    
    
    //支持向RequestBody类型转化
    if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
    
    
        
      //返回RequestBodyConverter实例
      return RequestBodyConverter.INSTANCE;
    }
    
    //除了RequestBody类型,不支持向其他类型转化,返回null
    return null;
  }

   static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
    
    
    static final VoidResponseBodyConverter INSTANCE = new VoidResponseBodyConverter();

    @Override public Void convert(ResponseBody value) {
    
    
      value.close();
      return null;
    }
  }

  static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
    
    
    static final RequestBodyConverter INSTANCE = new RequestBodyConverter();

    @Override public RequestBody convert(RequestBody value) {
    
    
      return value;
    }
  }

  static final class StreamingResponseBodyConverter
      implements Converter<ResponseBody, ResponseBody> {
    
    
    static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();

    @Override public ResponseBody convert(ResponseBody value) {
    
    
      return value;
    }
  }

  static final class BufferingResponseBodyConverter
      implements Converter<ResponseBody, ResponseBody> {
    
    
    static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();

    @Override public ResponseBody convert(ResponseBody value) throws IOException {
    
    
      try {
    
    
        // Buffer the entire body to avoid future I/O.
        return Utils.buffer(value);
      } finally {
    
    
        value.close();
      }
    }
  }

  static final class ToStringConverter implements Converter<Object, String> {
    
    
    static final ToStringConverter INSTANCE = new ToStringConverter();

    @Override public String convert(Object value) {
    
    
      return value.toString();
    }
  }
}


BuiltInConverters实现了Factory中的responseBodyConverterrequestBodyConverter方法,内部含有五个Converter默认实现类,在FactoryresponseBodyConverterrequestBodyConverter方法中分别返回这几Converter实例,其中只有ToStringConverter没有使用到,我们还发现了这五个Converterconvert方法的实现除了BufferingResponseBodyConverter,大部分都是,入参是是什么,返回就是什么,所以RetrofitConverter默认实现的convert方法大部分都没有对数据进行转化,返回原始数据,这些原始数据是String或来自OkhttpResponseBodyRequestBody,例如ResponseBodyConverterconvert方法就是返回OkhttpResponseBodyRequestBodyConverterconvert方法就是返回OkhttpRequestBody
Converter除了默认的返回原始数据,它还支持哪些数据转化呢?这个在retrofit-converters模块中可以找到答案,如下:

在这里插入图片描述
可以看到Retrofit还支持jsonxmlprotobuf等多种数据类型的转化,这些子模块都各自实现了retrofit模块暴露出来的Converter接口和Converter接口中的Factory接口,在Converteradapt方法中实现不同数据类型的转化逻辑,我们可以通过addConverterFactory(Factory)来支持不同数据类型转化的Converter工厂。

四 总结:

从整体来看,Retrofit的流程并不复杂,它的使用也非常简单.这主要得益于它优秀的框架,以及多种设计模式的巧妙运用.

其中最大的亮点就是动态代理模式,通过一个代理类InvocationHandler代理N多个接口,它把每一个方法的处理逻辑都集中到了invoke方法中,这样就能在同一处地方处理所有方法的注解解析。

Retrofit之所以这么受到编程人员的欢迎,很大程度是因为它CallAdapterConverter的引入,并且还是ArrayList集合的形式,它的高度灵活性,成为一款百搭网络请求库。

Retrofit的整体流程如下:
在这里插入图片描述

到此,Retrofit的整体流程分析完毕。

猜你喜欢

转载自blog.csdn.net/gaolh89/article/details/104496021