Android 网络框架之Retrofit源码解析

3,876 阅读17分钟

在使用了Retrofit之后,你是否会有这样的疑问:

1、为什么有OkHttp这么强大的网络框架了,Retrofit还能脱颖而出?
2、Retrofit是怎么适配第三方框架的?
3、Retrofit用了哪些设计模式?
4、Retrofit为什么好用?

下面我们就来探索Retrofit的真面目吧!

本文基于以下Java版本解析:

// retrofit
implementation 'com.squareup.retrofit2:retrofit:2.5.0'  
implementation 'com.squareup.retrofit2:converter-gson:2.0.2'  
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'

// rxjava
implementation 'io.reactivex.rxjava2:rxjava:2.1.6'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

本文目录:

  • 1、Retrofit存在的意义
  • 2、Retrofit的使用
  • 3、Retrofit的创建
  • 4、Retrofit.Builder的创建
  • 5、Retrofit的核心,动态代理
  • 6、Retrofit的动态代理
  • 7、总结

1、Retrofit存在的意义

Retrofit不是一个纯网络框架,为什么这么说呢? Retrofit是基于OkHttp框架来实现请求的,而Retrofit是基于OkHttp框架实现的一套封装,利用动态代理实现了简单的网络请求实现,并支持Gson,RxJava等第三方框架的适配,简而言之,就是让你的网络请求更便捷,更强大了;

那么Retrofit底层到底是怎么封装的呢? 是怎么变得更便捷,更强大了呢?

接下来让我们来深入源码,一探究竟!

2、Retrofit的使用

光说源码,不讲使用,总感觉有点被架空,容易找不到点;

那么接下来我们先来看一下Retrofit的简单使用吧;

Retrofit接口:

public interface GetRequestInterface {

    @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
    Call<ResultData> getCall();

    @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
    Observable<ResultData> getObservableCall();

    @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
    Call<StudentBean> getItem(@Query("student") String student,  @Query("type") String type);
}

基础请求URL:

public class BaseRequest {

    public static final String BaseURL = "https://fanyi.youdao.com/";

}

Retrofit的使用:

        // Retrofit 实例的创建
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BaseRequest.BaseURL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

        // 创建请求接口类
        GetRequestInterface request = retrofit.create(GetRequestInterface.class);
    	// ---普通网络请求---    
        // 获取请求对象Call
        Call<ResponseBody> call = request.getCall();
        // 执行网络请求
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                ResponseBody body = response.body();
                Log.i("TAG", "MainActivity onResponse response:" + response.toString());
                Log.i("TAG", "MainActivity onResponse body:" + (body == null ? "null" : body.toString()));
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.i("TAG", "MainActivity onFailure t:" + t.toString());
            }
        });
        
        // ---RxJava网络请求--- 
        Observable<ResultData> observableCall = request.getObservableCall();

        observableCall.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<ResultData>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(ResultData resultData) {
                        Log.i("TAG", "retrofit onNext resultData:" + resultData.toString());

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {
                        Log.i("TAG", "retrofit onComplete ");
                    }
                });

主要分为几步:

(1)通过构造者模式创建Retrofit实例;
(2)通过动态代理创建接口的实例;
(3)通过接口的实例获取到网络请求的操作类Call;
(4)通过Call来执行网络请求;

看一下大致流程图:

大致流程图

下面我们基于使用来深入框架,探索其源码的精妙!

3、Retrofit的创建

3.1、Retrofit的变量

        // Retrofit 实例的创建
        Retrofit retrofit = new Retrofit.Builder()
        		// 创建baseUrl
                .baseUrl(BaseRequest.BaseURL)
                // 添加GsonConverterFactory
                .addConverterFactory(GsonConverterFactory.create())
                // 添加RxJava的RxJavaCallAdapterFactory
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                // 构建Retrofit的实例
                .build();

Retrofit的构建使用了建造者模式,这个模式的优点就是可以构造复杂的对象,方便扩展,并且看起来代码比较简洁,美观;

在开始之前,我们先来看一下Retrofit的成员变量;

这里的变量并不是很多,我们来一个个分析;

**(1)Map<Method, ServiceMethod<?>> serviceMethodCache:**这是一个方法的缓存类,key为网络请求的Method,比如GET,POST等,而ServiceMethod则对应着动态代理解析后的方法类;
**(2)okhttp3.Call.Factory callFactory:**这个是创建OkHttp的工厂类;
**(3)HttpUrl baseUrl:**这个是基础URL,网络请求会带上这个基础URL;
**(4)List<Converter.Factory> converterFactories:**Converter.Factory的集合,Converter.Factory是将返回的数据通过这个工厂转化为对应的数据,比如Gson的GsonConverterFactory工厂类,也就是数据转化器工厂;
**(5)List<CallAdapter.Factory> callAdapterFactories:**CallAdapter.Factory的集合,CallAdapter.Factory是网络请求的适配器工厂,比如把Call转化为RxJava请求的RxJavaCallAdapterFactory工厂,也就是Call转化工厂;
**(6)Executor callbackExecutor:**用于回调网络请求;
**(7)boolean validateEagerly:**用于判断是否需要立即解析方法,这个我们在将动态代理的时候会讲到;

我们看完了Retrofit的成员变量,但是Retrofit的创建是通过Builder来创建的,下面我们来看看Retrofit的Builder的变量有哪些,分别有哪些作用;

4、Retrofit.Builder的创建

4.1、Retrofit.Builder的变量

从图片可以看出,和Retrofit的变量差不多,唯一有区分的就是多了Platform和validateEagerly变量,让我们通过源码来看看这两个是做什么的;

先来看一下这个Platform的赋值;

这个Platform是通过Platform.get()方法获取的,来看看这个方法是啥逻辑;

从图片可以看出,最终是调用的findPlatform()方法;

这个方法会返回Android,Java,Platform等类,主要是用来判断对于的平台,然后获取到对于的Platform;

private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      // 判断从系统中获取到的SDK不为0的时候,则为Android平台;
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      // 如果不是Android平台的话,那么就返回Java的平台;
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    // 默认的返回值;
    return new Platform();
  }

而Build.VERSION.SDK_INT的判断逻辑为:

翻译过来的意思就是:

当前在此硬件上运行的软件的SDK版本。这个值在设备启动时不会改变,但可能会在硬件制造商提供OTA更新时改变;

下面我们来看一下这个Android类对应的源码:

Android类对应的源码不多,就几个方法,这里我们重点关注下面这几个方法:
**(1)defaultCallbackExecutor():**默认的线程执行器Executor,从源码可以看出,获取的是主线程的Hander,execute的时候,会post到主线程执行;
**(2)defaultCallAdapterFactories:**获取默认的CallAdapter.Factory,用于创建CallAdapter;
**(3)defaultConverterFactories:**获取默认的数据转换工厂ConverterFactory,用于创建转换器Converter;

总结:Platform主要是用于适配不同的平台,用于获取默认的Executor,请求适配器工厂类CallAdapterFactory,数据转换工厂类ConverterFactory等;

4.2、baseUrl

baseUrl,是我们网络请求的基础URL;

我们进源码里面看一下,具体做了啥操作;

这里主要做了两步操作:
1、首先第一步是通过解析这个baseUrl并返回一个HttpUrl对象; 2、第二步是将第一步创建的HttpUrl对象赋值给Builder;

这里我们主要看第一步的具体操作,这里的逻辑是在HttpUrl的 parse(@Nullable HttpUrl base, String input)里,通过解析URL,判断该请求的scheme是为http还是https,如果不是这其中一个,那么就会抛出异常,源码我们大致看一下;

然后下面还会解析URL,获取到主机地址host,端口号port,具体源码我就不贴了,感兴趣的可以跟着源码看一下;

4.3、Converter.Factory

这个我们上面在接受Retrofit的成员变量的时候有提过,是用于创建Converter的工厂,使用了抽象工厂的设计模式,而Converter是用来将请求返回的数据,转化为对应平台的数据,而这里,我们使用的是Gson平台;

我们先来看一下这个Converter.Factory,看看其背后是怎么实现的;

从源码可以看出,Converter.Factory是Converter的内部类,主要有两个方法,一个是requestBodyConverter,用于将请求的RequestBody转换为对应的转换器Converter;

另一个方法是responseBodyConverter,用于将返回的返回体ResponseBody转换为对应的转换器Converter;

而转换器Converter里面只有一个方法convert,用于将返回的数据转换为对应的类型;

我们在创建Retrofit的实例时,是通过GsonConverterFactory.create()来创建对应的转换器工厂的,下面我们来看看这个Gson的转换器工厂是怎么实现的;

先来看一下这个create()的方法;

最终是走的这里,进行了简单的赋值;

GsonConverterFactory这个工厂最重要的还是responseBodyConverter和requestBodyConverter方法,下面我们来具体分析;

  • requestBodyConverter:

在requestBodyConverter方法里面,通过class的Type类型,创建了Gson的TypeAdapter,这个TypeAdapter很熟悉,就是我们使用gson解析会用到的类,最终通过TypeAdapter和gson的参数创建了GsonRequestBodyConverter对象,下面来瞄一眼这个类的代码;

这个类的源码很简单,我们主要convert()这个方法;

这个方法的逻辑就是将传进来的value值通过TypeAdapter将其转化为ByteString,然后再传进RequestBody作为参数来构建RequestBody对象;

这个方法我们先了解到这里,后面在这个requestBodyConverter调用的地方再来讲一下;

  • responseBodyConverter:

这个方法和上面那个requestBodyConverter方法有点类似,也是通过class的Type类型,创建了Gson的TypeAdapter,最终通过TypeAdapter和gson的参数创建了GsonResponseBodyConverter,同理,我们也来看一下这个类的实现吧;

源码很简单,这里我们也是关注convert()这个方法;

这里的逻辑有没有很熟悉,就是我们经常用的gson解析,通过TypeAdapter读取JsonReader的数据,返回对应的数据类型,这里的参数ResponseBody就是我们上面GsonRequestBodyConverter的convert方法生成的;

到这里GsonConverterFactory就讲的差不多了,后面我们在用到的地方再详细讲一下;

4.5、CallAdapter.Factory

CallAdapter.Factory,从命名可以看出,是用来创建CallAdapter的工厂类,使用了抽象工厂的设计模式,而CallAdapter是用于将Call转化为我们所需要的请求类型,比如将Call转化为RxJava的调用类型;

而CallAdapter里面是通过adapt方法来进行转换的,adapt是接口的一个方法,交给子类去实现,这个方法的逻辑,我们下面将Retrofit的解析时,再统一讲解,这里是需要了解这是一个转换的方法即可;

下面我们来看看创建CallAdapter的工厂里面都有哪些方法,分别是用来干嘛的;

这个Factory的逻辑很少,只有几个方法,这里我们主要关注get方法,通过get方法来获取CallAdapter的对象,同理,这里也是交给子类去实现;

而上面我们Retrifit的创建,在CallAdapter.Factory的添加时,使用了RxJava的工厂,也就是RxJava2CallAdapterFactory,用于将Call请求转换为RxJava对应的请求;

下面我们来看看这个RxJava2CallAdapterFactory的实现逻辑吧;

RxJava2CallAdapterFactory的创建,也是通过RxJava2CallAdapterFactory.create()的方法,那么我们来看下这个create方法做了啥?

只是简单的new了一个RxJava2CallAdapterFactory,而构造方法里也没有其他的逻辑了,只是对Scheduler进行赋值,而这里创建时,传的是null;

上面我们看完RxJava2CallAdapterFactory的创建后,下面我们来看一下RxJava2CallAdapterFactory是怎么通过get方法创建一个CallAdapter的;

public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class<?> rawType = getRawType(returnType);

    if (rawType == Completable.class) {
      // 创建RxJava2CallAdapter
      return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
          false, true);
    }
	...
	// 创建RxJava2CallAdapter
    return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
        isSingle, isMaybe, false);
  }

这个方法职责很明确,就是根据各种参数来创建RxJava的CallAdpter,也就是RxJava2CallAdapter;

这里我们来重点关注一个RxJava2CallAdapte的adapt方法的逻辑;

public Object adapt(Call<R> call) {
	// 第一步:根据是否是异步的参数创建对应的Observable
    Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call);

    Observable<?> observable;
    // 第二步:根据各种判断,再封装一层Observable返回
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }
    ... 
    return observable;
  }

这个方法的逻辑并复杂,主要是将Call请求转化为RxJava的请求,最终返回一个RxJava的被观察者:Observable,用于进行RxJava类型的网络请求,如上面的示例;

这个方法的逻辑主要有两步,我们先来看一下第一步创建的被观察者,这里会先判断是否是异步,如果是异步的话,那么就创建CallEnqueueObservable,否则就创建CallExecuteObservable;

这两个的区别就是,在调用订阅(subscribe)的时候,会执行CallEnqueueObservable的subscribeActual方法,最终是通过OkHttpCall的enqueue方法来执行异步请求;

而CallExecuteObservable在调用订阅(subscribe)的时候,也会执行CallEnqueueObservable的subscribeActual方法,在这个方法里,就直接调用OkHttpCall的execute方法来执行同步请求;

而第二步的封装,这里我们主要以BodyObservable来进行讲解,这个类会对订阅的观察者进行封装,在onNext方法中将body返回;这一步可以理解为对返回的结果进行处理;

这里是RxJava的用法,我默认你是会的,如果对RxJava还不熟悉的同学,可以后面去看看RxJava的用法;

到此,Retrofit的CallAdapter.Factory的逻辑就先告一段落了,下面我们来看看Retrofit的最终build()方法的逻辑;

4.5、Retrofit.Builder#build

废话不多说,我们直接撸源码;

public Retrofit build() {
      // 判断当callFactory(OkHttpClient)为空,就重新创建一个OkHttpClient进行赋值;
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

	  // 判断Executor为空时,就用Platform的默认Executor进行赋值,上面我们讲过,这里面使用的是主线的的Handler;
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // 通过添加的CallAdapter.Factory来创建一个新的CallAdapter.Factory集合;
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
     
// 添加Platform的默认CallAdapter.Factory,如果我们没有添加CallAdapter.Factory,那么就会使用这个Platform的默认CallAdapter.Factory;     				callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      // 创建Converter.Factory的集合
      List<Converter.Factory> converterFactories = new ArrayList<>(
          1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      // 添加默认的Converter.Factory
      converterFactories.add(new BuiltInConverters());
      // 添加自定的Converter.Factory
      converterFactories.addAll(this.converterFactories);
      // 添加Platform的默认Converter.Factory
      converterFactories.addAll(platform.defaultConverterFactories());
	  // 最终创建Retrofit实例;
      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }

这个build()方法,主要是做各种参数的赋值,最终通过参数来创建Retrofit的实例,那么到这里Retrofit的创建就差不多将完了,下面我们将会学习到Retrofit的核心;

为什么我们可以通过接口定义一个类型,就可以执行请求了,对于这些方法的解析,以及参数的赋值的操作是在哪里呢?

这么就涉及到Retrofit使用的一个很重要的设计模式了,也就是动态代理设计模式;

5、Retrofit的核心,动态代理

5.1、什么是代理?

举个例子,假如我要去超市买水果,可是我好懒,周末就想呆在家里不想出门,但是心里又很想吃水果,那怎么办呢?

只能打开外卖App,在上面买完之后,由外卖小哥送过来,这时候,我就通过中介,外卖App来买到水果,而这个过程叫做代理;

不直接操作,而是委托第三方来进行操作,从而达到目的;

而Java的代理分为静态代理和动态代理;

5.2、什么是静态代理?

如果代理类在程序运行之前就已经存在了,那么这种代理方式就被称为静态代理;

还是以上面的例子,我要买水果,来定义一个买水果的接口Operator;

public interface Operator {
	// 买水果
	void buyFruit();
}

而我们的代理类外卖App需要实现这个接口,同时,将需要委托的对象传进来,在buyFruit的过程中,做了一些出来,比如去超市取货,取完货之后,再送货;

public class AppAgent implements Operator {
    
    private Operator operator;

    public AppAgent(Operator operator) {
        this.operator = operator;
    }

    @Override
    public void buyFruit() {
    	// 1、在App上,提供商品给用户下单
        
        // 2、根据订单去超市采购水果
        operator.buyFruit();
        
        // 3、送货给客户
    }
}

委托的对象,超市:

public class Market implements Operator {

    @Override
    public void buyFruit() {
		// 到超市买水果
    }
}

那么最终的实现效果就是,我们通过外卖App的一顿操作,从超市买到了水果,如下:

public class Main {

    public static void main(String[] args) {

        // 委托对象,超市;
        Market market = new Market();
        // 代理对象,外卖App;
        AppAgent appAgent = new AppAgent(market);
        // 通过外卖App的代理,从超市买到了水果;
        appAgent.buyFruit();
    }
}

以上就是我们静态代理的过程,这个例子只是举了买水果这个过程,但是如果我还想要买菜,买生活用品等一系列东西呢?

我就得在接口Operator里面再多新增好几个方法,同样的代理类也要跟着去重写一堆的方法,但是这些方法做的操作其实都是一样的,都是买这个动作,但是我们不得已,新增一种类型,我们就得在代理类里面再重写并调用;

那么这个过程其实是可以抽出来的,这种方式就叫做动态代理;

5.3、动态代理

动态代理,和静态代理不同的是,动态代理的方法是运行后才创建的,而静态代理是运行前就存在的了;

说白了,和静态代理不同的是,动态代理的方法都是在运行后,自动生成的,所以叫动态代理;

下面我们来看看动态代理是咋用的;

在使用动态代理的时候,被代理类需要实现InvocationHandler这个接口,,这个invoke方法是在动态生成的代理类中调用的,对应着我们上面在静态代理operator.buyFruit()这个方法的调用,下面来看一下这个方法对应的参数;

public interface InvocationHandler { 
  // Object proxy:接口的具体实现类;
  // Method method:解析之后自动生成的方法;
  // Object[] args:方法对于的参数;
  Object invoke(Object proxy, Method method, Object[] args);
}

而最终运行时生成的代理类,一般名称会是Proxy0Proxy0, Proxy1这种,通过Proxy.newProxyInstance()方法来生成的,这个下面会讲到,先来看一下下面的伪代码;

public final class $Proxy0 extends Proxy implements Operator { 
	public final boolean buyFruit() { 
    	// h是InvocationHandlel,调用了invoke方法;
    	super.h.invoke(this, m1, (Object[])null); 
    }
  }
}

在生成的代理类中,会实现我们的接口,并重写方法,在方法里面通过InvocationHandler回调参数到invoke方法里,最终通过反射调用被代理对象的方法;

而我们通过实现这个InvocationHandler接口,在invoke方法里面,通过method.invoke(object, args)可以来调用被代理的方法,然后我们可以在这个method.invoke(object, args)之前或者之后做一些处理,这样所以的方法都可以一并进行处理,而不是每次新增一个方法,就得重写一遍逻辑;

下面来看一下具体实现:

public class CustomProxy implements InvocationHandler {

    private Object object;

    public CustomProxy(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 1、在App上,提供商品给用户下单
        // doSomeThing();

        // 2、根据订单去超市采购东西(在这个方法之前或者之后都可以统一处理操作)
        Object invoke = method.invoke(object, args);

        // 3、送货给客户
        // doSomeThing();
        return invoke;
    }
}

下面来看一下,最终的调用;

public class Main {

    public static void main(String[] args) {
        // 创建被代理类
        CustomProxy customProxy = new CustomProxy(new Market());
        // 动态生成代理类
        Operator proxyInstance = (Operator) Proxy.newProxyInstance(Operator.class.getClassLoader(), new Class[]{Operator.class}, customProxy);
        // 调用对应的方法
        proxyInstance.buyFruit();
    }
}

这里通过Proxy.newProxyInstance()方法,动态生成代理类$Proxy0这种,这里涉及到的反射的知识,就不再赘述了;

然后动态代理类调用方法,最终会走到CustomProxy的invoke()方法,然后我们在这个方法里面通过method.invoke(object, args)来进行最终的代理调用,而在这个最终的代理调用的前后,我们可以实现自定义的逻辑;

这个实现了InvocationHandler接口的CustomProxy,更像是一个拦截类,在代理方法的调用过程中进行拦截,然后再实现我们的自定义逻辑;

至此,动态代理你理解了吗?没有理解也没关系,多看几遍,多练几遍就可以了;

6、Retrofit的动态代理

6.1、Retrofit为什么要使用动态代理?

首先,让我们来想一个问题,Retrofit为什么要使用动态代理?

使用动态代理的好处就是在调用方法之前,我们可以统一做一些操作,而不必新增一个方法就去写一遍逻辑;

而Retrofit巧妙的使用了动态代理在调用接口的方法之前,统一的去解析处理Header和URL等操作;

这样就不用每次在新增一个请求的方法,就去写一遍这个解析的逻辑;

那么接下来我们来看看Retrofit的怎么解析这些接口的;

6.2、Retrofit是怎么使用动态代理的?

下面我们来看一下Retrofit的create的方法,动态代理的逻辑是在这里实现的;

public <T> T create(final Class<T> service) {
    ...
    // 验证接口的参数以及配置是否正确
    if (validateEagerly) {
      eagerlyValidateMethods(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 Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // 判断是否是Object,如果是的话,就直接调用方法返回
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            // 判断是否是Java8平台的默认方法类型,如果是的话,就调用Java8平台的invokeDefaultMethod方法
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            // 解析方法;
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

这里我们将这个方法分为两步;

** 第一步:** eagerlyValidateMethods方法,这个方法的逻辑是用于加载接口的配置,用于判断接口对应的header,body以及方法的参数等配置是否正确,如果不正确那么就会抛出异常;

** 第二步:** loadServiceMethod方法,这个方法的逻辑主要是用于解析我们在接口配置的注解以及参数,比如header,body,url等等;

这里我们重点关注第二步的loadServiceMethod方法方法;

我们来看一下其源码的具体实现;

ServiceMethod<?> loadServiceMethod(Method method) {
    // 先从缓存map集合里面获取ServiceMethod;
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        // 如果从缓存map里面获取不到ServiceMethod,那么再通过解析注解,获取到ServiceMethod对象;
        result = ServiceMethod.parseAnnotations(this, method);
        // 将解析后的ServiceMethod对象存入到map集合中;
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

这里做的操作很简单,就是获取ServiceMethod,而在获取ServiceMethod的过程中,会先从缓存的map中获取,如果获取不到了再进行解析,这样就不必获取一次ServiceMethod,就去解析一次,比较耗性能;

而这个ServiceMethod的类是个抽象类,只有两个方法,一个是静态的parseAnnotations方法,一个是抽象的invoke方法;

我们先来看一下这个parseAnnotations方法;

static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
	// 通过解析接口方法的注解,获取RequestFactory
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

   	...
    // 解析注解并获取ServiceMethod对象
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

这个方法的逻辑也不是很复杂,主要分为两步;

第一步: 获取RequestFactory;
第二步: 获取ServiceMethod;

我们先来看第一步的操作;

static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }

通过Builder来创建RequestFactory,来看看这个Builder做了啥操作;

Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      // 获取方法所有的注解,包括自己声明的以及继承的
      this.methodAnnotations = method.getAnnotations();
      // 获取方法参数的所有类型,包含泛型;
      this.parameterTypes = method.getGenericParameterTypes();
      // 获取方法参数上的所有注解
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

这个方法的逻辑很简单,就是做一些赋值操作,这里需要注意的是这几个反射的方法,下面的build方法会用到;

RequestFactory build() {
      for (Annotation annotation : methodAnnotations) {
        // 遍历方法的注解,解析方法的参数配置,获取到请求的url,header等参数
        parseMethodAnnotation(annotation);
      }

      ...
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        // 遍历方法的参数,以及参数的类型,解析方法的参数逻辑
        parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);
      }

      ...
      // 根据上面解析的参数配置,创建RequestFactory
      return new RequestFactory(this);
    }

这个方法的逻辑就比较重要了,我们在接口的方法里面定义的相关url,header等注解,最终就是在这里解析并转化为okhttp请求的Call,那么我们来看看这里到底是怎么解析的;

先来看一下parseMethodAnnotation这个方法, 这个方法的主要逻辑是用于解析方法注解的配置信息;

下面我们来看看这个类的具体实现;

这个方法的逻辑比较多,我们大致看一下就可以了,这里面做的主要职责就是通过注解Annotation,获取到url,header,isMultipart等参数,并将其赋值给建造者Builder的成员变量;

对于这个方法,这里就不多说了,感兴趣的跟着源码去看一下;

而第二个方法parseParameter,也是遍历上面获取到的方法的参数类型parameterTypes以及方法参数的注解parameterAnnotationsArray,来解析并获取相关配置,而这个方法最终是调的parseParameterAnnotation方法的逻辑;

主要是用于解析这里的逻辑:

下面我们来看看具体实现;

这个parseParameterAnnotation方法的逻辑和上面的parseMethodAnnotation方法有点类似,也是通过判断对于的类型来进行解析,这里源码过长,就不贴出来了;

这里我们就找其中一个Query的解析来进行分析;

省略前面的代码
... 
 else if (annotation instanceof Query) {
        ...
        // 将注解annotation强转为Query
        Query query = (Query) annotation;
        // 获取注解Query对应的值;
        String name = query.value();
        ...
        if (Iterable.class.isAssignableFrom(rawParameterType)) {
          // 判断这个参数的类型为Class类型;
          ...
          // 创建ParameterHandler的子类Query
          return new ParameterHandler.Query<>(name, converter, encoded).iterable();
        }
        ...
      }
...
省略后面的代码

这里最终解析获取的是ParameterHandler.Query类,这个类里面有个apply的方法,会在接口请求的时候会调用到,目的是通过请求的RequestBuilder将解析出来的参数,添加到RequestBuilder里去;

这里我们了解一下就可以了;

这里还有一个需要注意的点,就是这里的解析,涉及到Converter这个convert方法的逻辑;

这里我以Body为例,在Body这个类的apply方法里,会通过Converter这个convert方法,将body参数转化为对应类型的数据;

这个apply的方法是在进行网络请求的时候会调用,具体调用链如下,这里以RxJava为例:

1、RxJavaCallAdapterFactory.ResponseCallAdapter的adapt方法;
2、RxJavaCallAdapterFactory.CallOnSubscribe的call方法;
3、RxJavaCallAdapterFactory.RequestArbiter的request方法;
4、OkHttpCall的execute方法;
5、OkHttpCall的createRawCall方法;
6、RequestFactory的create方法;
7、ParameterHandler的apply方法;

最终在这里触发了apply方法的调用,这里源码就不贴出来了,感兴趣的朋友,可以跟着源码去看一遍;

我们上面看的RequestFactory的build方法的最后一个,创建RequestFactory,这里的逻辑就是将我们上面解析出来的参数,给这个RequestFactory进行赋值;

那么到这里parseAnnotations的第一步就讲完了,先来总结一下,这一步主要是解析方法注解和方法参数的注解,从而获取到对应的参数配置,最终将其赋值给RequestFactory对象;

下面我们来看HttpServiceMethod的parseAnnotations方法;

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
     // 创建CallAdapter
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
    ...
	// 创建Converter
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

	// 通过参数创建HttpServiceMethod
    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
  }

这个方法的逻辑并不复杂,主要分三步:

第一步: 创建CallAdapter;
第二步: 创建Converter;
第三步: 通过参数创建HttpServiceMethod;

这里主要关注的是前两步,创建了CallAdapter和Converter;

我们先来看一下第一步的逻辑;

这里的调用链是这样的,首先调用了HttpServiceMethod的createCallAdapter方法,然后再调用了Retrofit的callAdapter方法,最后调用了Retrofit的nextCallAdapter方法;

我们来看看nextCallAdapter的逻辑;

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    ...
	// 通过callAdapterFactories的get方法来创建CallAdapter
    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

   ...
  }

这里的逻辑不复杂,最终通过CallAdapter.Factory来创建CallAdapter,而这个CallAdapter.Factory的逻辑我们上面已经讲过了,就是用来创建CallAdapter的工厂;

下面我们来看第二步的调用;

第二步的调用链是这样的,先调用HttpServiceMethod的createResponseConverter方法,然后再调用Retrofit的responseBodyConverter方法,最终调用了Retrofit的nextResponseBodyConverter方法,我们来看看nextResponseBodyConverter这个方法的逻辑;

public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    ...

    int start = converterFactories.indexOf(skipPast) + 1;
   // 先通过Converter.Factory工厂创建Converter,再通过Converter来转化返回的数据
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter<ResponseBody, T>) converter;
      }
    }

    ...
  }

第二步的逻辑和第一步类似,最终通过Converter.Factory工厂的responseBodyConverter方法创建了Converter,而这个Converter.Factory的逻辑,我在上面也已经讲过了;

而这个Converter获取的是返回体的Converter,用于将返回的数据转化为对应的平台的数据,比如Gson,而这里的Converter的convert的方法,最终是在OkHttp的网络请求成功之后调用的,具体调用链如下:

1、OkHttpCall的enqueue方法;
2、OkHttpCall的parseResponse方法; 3、Converter的convert方法;

调用链也不是很复杂,感兴趣的朋友可以跟着源码去看一下,这里就不贴源码了;

那么到这里,HttpServiceMethod的parseAnnotations方法就已经讲完了;

下面,我们回到Retrofit的create这个方法,在调用完loadServiceMethod方法之后,会调用ServiceMethod的invoke方法,这个方法是个抽象方法,具体实现在子类;

最终实现是在HttpServiceMethod的invoke方法里;

在这里调用了CallAdapter的adapt方法,将请求call转化为对应平台的请求类型,比如RxJava的类型,这个上面也已经讲过了,忘了的朋友,可以往前翻翻;

7、总结

从上面的分析可以看出,Retrofit最重要的点,就是动态代理,在动态代理的时候做了很多逻辑处理,简化我们后面的调用等等;

下面我们来看最终的总结流程图:

其他

Android 你不得不学的HTTP相关知识

Android 网络编程之TCP、UDP详解

Android 网络编程之HTTPS详解

Android 网络框架之OkHttp源码解析

关于我

兄dei,如果我的文章对你有帮助的话,请帮我点个赞吧️,也可以关注一下我的Github博客;