Retrofit 源码分析

在分析 Retrofit
源码之前,你首先得理解动态代理模式,因为Retrofit是通过动态代理的方式进行统一网络请求接口类的处理。Retrofit的代码量并不大,只是对OkHttp进行了封装,用更少的代码进行网络请求,明白动态代理模式之后,再看Retrofit网络请求处理流程就很清楚了。少量的代码使用大量的设计模式,所以Retrofit框架很值得我们去研究。

关于Retrofit的使用这里就不再赘述了,还不太了解Retrofit使用的同学
Retrofit简介
今天我们来聊一聊Retrofit的内部实现,通过源码来分析Retrofit的整个执行顺序。

本文将顺着构建请求对象->构建请求接口->发起同步/异步请求的流程,分析Retrofit是如何实现的。

1.基本使用

参照官方网站实例:
(1) 创建一个java接口用来作为http请求

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

(2) Retrofit类会自动实现这个GitHubService接口

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

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

(3)
返回的GitHubService是一个retrofit所实现的代理对象,然后调用此方法来包装了一个对于http的请求

Call<List<Repo>> repos = service.listRepos("octocat");

此Call对象即可对于网络请求做同步或者异步请求操作。

最近非常流行 Retrofit+RxJava+OkHttp
这一整套的网络请求和异步操作的开源框架,从 Jake
Wharton 的
Github 主页也能看出其趋势。

  1. 配置Retrofit对象(与OkHttp相同,采用Builder模式)

在没有框架的时候,做一次网络请求大概会经过五个步奏:

开始之前,我们先看下Retrofit的基本使用方式

2.源码解析

(1)
查看Reftrofit的源码目录树,查看代码,所包含的类很少,http子目录下都是定义接口时的注解信息,如常用的@GET,@POST等,查看它的代码是添加了注解,具体对于注解相关理解可以请看注解介绍。

/** Make a GET request. */
@Documented
@Target(METHOD)//用来修饰方法
@Retention(RUNTIME)//运行时保留
public @interface GET {
  /**
   * A relative or absolute path, or full URL of the endpoint. This value is optional if the first
   * parameter of the method is annotated with {@link Url @Url}.
   * <p>
   * See {@linkplain retrofit2.Retrofit.Builder#baseUrl(HttpUrl) base URL} for details of how
   * this is resolved against a base URL to create the full endpoint URL.
   */
  String value() default "";
}

(2)
从上面的基本操作上我们可以查看一下Retrofit的源码,先从retrofit.create来看,如何声明了一个接口,转化成了一个可以访问http请求的操作。
Retrofit可以看成一个适配类,它是通过注解将一个java接口返回成一个http调用。Retrofit类先通过一个Builder模式定义一个Retrofit实例,然后调用Retrofit.create()方法:

@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
  public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, 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);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

关键点为:Proxy.newProxyInstance()方法,我们自己通过建立一个Interface,然后由Proxy为我们生成一个代理对象,会调用InvocationHandler类中的invode()方法,然后会调用此方法去做一些统一操作,真正的操作在serviceMethod.callAdapter.adapt(okHttpCall)此行代码中。
(3)接下来查看ServiceMethod类,分析callAdapter.adapt()此方法具体干了什么事情。
通过此类的描述即可知道,它就是真正的适配器,将接口转化成http的调用。

Adapts an invocation of an interface method into an HTTP call.

内部也是使用Builder来实例化对象,具体查看callAdapter,在createCallAdapter()方法中,

return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);

还是在retrofit类中创建的

int start = adapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

是从adapterFactories列表中获取的,查看此列表的初始化为:

public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

这个我们就清楚理如果在Retrofit.Builder中设置了addCallAdapterFactory()此方法,那么就用此的adapt来实现接口的具体操作,例如我们可以使用RxJavaCallAdapterFactory.create(),那么返回的就是一个Observable了,而不是默认的Call类类,我们直接查看默认的Call类是如果来实现adapt()方法的.

adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

所有的adapterFactory都要实现CallAdapter.Factory接口,它其中就定义了在retrofit中调用的adapt方法,它有两个实现类为DefaultCallAdapterFactory.javaExecutorCallAdapterFactory.java,我们直接查看DefaultCallAdapterFactory.java这个简单的类即可:

@Override public Call<Object> adapt(Call<Object> call) {
        return call;
      }

ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);

它就是返回了Call这个类,从最开始Retrofit中的方法,我们可以知道它所返回的就是OkHttpCall这个类,那么看这个OkHttpCall的同步和异步的网络请求即可,这个流程,我们从锁定定义的Interface类,然后Retrofit类的create方法,通过ServiceMethod的一系列转化,最后变成了CallAdapter这个接口的具体实现类,所传递的参数为OkHttpCall类,它是对于OkHttpCall类的封装,所返回的就是一个http请求。
(4) 我们接下来查看ServiceMethod还做了哪些工作
主要的操作在Builder.build()
responseType:从一个http的响应部分转化成为一个java对象,它就是Call<Repo>中的Repo.
responseConverter:它是通过Retrofit.addConverterFactory()来用于解析为一个java对象,我们一般都是在http请求JSON对象,转化成为java类,那么就可以传入GsonConverterFactory.create()
methodAnnotations:
注解方法,它是通过parseMethodAnnotation来进行解析,不同的注解传输不同的值,同意调用parseHttpMethodAndPath来拼接请求url,用来网络请求。
parameterHandlers:用来解析在API定义方法是后的参数。parseParameterAnnotation()方法用来解析没一个参数的注解,例如@Query,@Path

(5) 接下来查看http请求操作
具体的接口为retrofit2.Call类,具体的实现类为OkHttpCall.java,我们直接查看我们所常用的enqueue奥门威尼斯网址,异步方法:

okhttp3.Call call;
...
...
call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callSuccess(Response<T> response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });

这一段代码,就可以明显的看出,上述的OkHttpCall就是对于okhttp3.Call类的封装,然后通过我们自己索要实现的Callback接口来完成onResponse等操作。
以上代码的分析就是一个从创建Retrofit类到最后http异步请求完成的流程。

(5) 接下来是看它如何解析http请求的,直接看异步操作了,同步操作同理

private okhttp3.Call createRawCall() throws IOException {
    Request request = serviceMethod.toRequest(args);
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

异步操作中Call的生成,Request定义的为一个http的请求,它的产生要去ServiceMethod.toRequest()方法中去看,

RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart);

利用ServiceMethod中的方法配置来(就是我们新建Retrofit.Builder的配置)配置Request

ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
...
...
for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }

最后是由ParameterHandler来操作的,查看此类就可以发现它是对于我们所自己定义的接口方法中的参数的处理,例如:
@Path@Query的处理,这个就是将我们之前在ServiceMethod中所对于方法和参数的解析,在此使用了。然后调用了
serviceMethod.callFactory.newCall()此方法来返回一个Call对象。callFactory是从retrofit类中来的,就是我们在Builder.client()中所调用的方法,这个就是OkHttpClientRequest类中就是我们的http的请求信息,然后用个OkHttpClient来做具体的请求。parseResponse是用来解析相应的方法,最后会调用ServiceMethod.toResponse(),就是通过配置的responseConverter类解析相应的信息的,用GsonConverterFactory.create()就是将JSON转化成了java类对象。
这就是使用默认一般操作的从请求到响应的代码流程.

奥门威尼斯网址 1

Retrofit retrofit = new Retrofit.Builder().baseUrl.build();

  • 构建request的参数
  • 手动开启子线程做http请求
  • 在子线程的run方法中具体请求
  • 拿到返回的response数据后,回调给上一层
  • 在主线程中更新UI

Step1:

Retrofit+RxJava+OkHttp.png

  1. 创建请求接口类

如果没有网络请求框架,然后对多线程又不是太熟悉,就会出现很多问题。比如,请求是否异步,这里就会出现android中常见的错误:Null
pointer exception。
所以,在我们还没有造轮子的能力的时候,多去看看优秀框架的源码是有好处的,整个框架的搭建,运用了哪些设计模式,容错处理等等。。

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

本文主要介绍 Retrofit 的基本原理,基于
2.1.0
版本的源码。

Retrofit 获取实例

  • 首先通过构建者模式去获得Retrofit实例

 Retrofit retrofit = new Retrofit
                .Builder()
                .baseUrl(ApiContancts.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
  • 我们来看看build()方法中具体做了什么

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

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }

不难看出build()方法中主要做了判空处理:
1.baseurl为空,抛出异常;
2.callFactory为空,默认使用OKhttp3的callFactory,这一点也可以看出Retrofit是基于okhttp3做的封装。不会支持URLConnection和OkHttpClient了。
3.callbackExecutor为空,会通过Platform这个类使用defaultCallbackExecutor

 static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

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

跟踪源码会发现,最终会通过Handler去做操作。
4.第一个List集合是存储刚刚那个callbackExecutor,第二个List集合是存储将Json转换成实体类的一个工厂或者说是适配器。
5.最后返回一个Retrofit的实例。

Step2:

1. 基本用法

 public interface NetworkInterface { @GET Call<MyResponse> listRepos(); //不同的方法代表不同的网络请求,可以声明请求方式(GET、POST..),请求头Header参数,请求体信息。 ....}

Retrofit实例的create()方法

Call<CookListModel> cook = retrofit.create(ApiService.class).getCook(1,20);

通过调用create()方法

 public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, 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);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

其实我看到这里也很懵逼,我们的Http请求方法、参数是通过注解的方式创建的,它是怎么转换成实体对象的?
不急,我们一步一步的看下去

ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

这里也用了构建者模式,build()方法中调用parseMethodAnnotation()去解析注解

  private void parseMethodAnnotation(Annotation annotation) {
      if (annotation instanceof DELETE) {
        parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
      } else if (annotation instanceof GET) {
        parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
      } else if (annotation instanceof HEAD) {
        parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
        if (!Void.class.equals(responseType)) {
          throw methodError("HEAD method must use Void as response type.");
        }
      } else if (annotation instanceof PATCH) {
        parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
      } else if (annotation instanceof POST) {
        parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
      } else if (annotation instanceof PUT) {
        parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
      } else if (annotation instanceof OPTIONS) {
        parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
      } else if (annotation instanceof HTTP) {
        HTTP http = (HTTP) annotation;
        parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
      } else if (annotation instanceof retrofit2.http.Headers) {
        String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
        if (headersToParse.length == 0) {
          throw methodError("@Headers annotation is empty.");
        }
        headers = parseHeaders(headersToParse);
      } else if (annotation instanceof Multipart) {
        if (isFormEncoded) {
          throw methodError("Only one encoding annotation is allowed.");
        }
        isMultipart = true;
      } else if (annotation instanceof FormUrlEncoded) {
        if (isMultipart) {
          throw methodError("Only one encoding annotation is allowed.");
        }
        isFormEncoded = true;
      }
    }

那么,Retrofit到底是怎么把我们定义的接口转换成http请求的呢?
我们来看看ServiceMethod这个类。

Adapts an invocation of an interface method into an HTTP call.

ServiceMethod这个类相当于一个适配器,将interface转换成http的请求,再通过OkHttp去做网络请求。
所以说,真正的关键代码是:

ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);

Retrofit内部大致的执行流程就是这样,如果想要更深入的去研究Retrofit的话,建议大家利用debug一步一步的跟踪源码分析,这样的话会更加容易理解一点。

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .addConverterFactory(GsonConverterFactory.create()) // json response
    .build();

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

1.1 定义 API 接口

Retrofit 的使用非常简单,先来看一个
官网
上的示例代码。

public interface GitHubService {
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
}

官方的解释是

Retrofit turns your HTTP API into a Java interface.

首先定义了一个 API 接口 GitHubService,包含 HTTP 请求的方法 GET
和参数 user,及成功后的返回类型
List<Repo>,方法和参数由注解声明,非常清晰。

  1. 创建接口类实例

Step3:

1.2 创建 Retrofit 对象并生成 API 实例

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

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

然后创建一个 Retrofit 对象,这里采用 Builder 模式,传入 baseUrl
ConverterFactory 等参数,后面会讲到。

通过 Retrofit 对象用动态代理的方式生成我们需要的 API 实例
GitHubService

NetworkInterface networkInterface =
retrofit.create(NetworkInterface.class);

Call<List<Repo>> repos = service.listRepos("octocat");

// async(异步方式)
repos.enqueue(new Callback<List<Repo>>() {
    @Override
    public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
        if (response.isSuccessful()) { // successful response
            List<Repo> repos = response.body(); // converted response
        }
    }

    @Override
    public void onFailure(Call<List<Repo>> call, Throwable t) {}
});

1.3 API 实例去请求服务

Call<List<Repo>> repoCall = service.listRepos("danke77");

用生成的 API 实例调用相应的方法,默认返回 Call<T>,然后调用
Call#execute 方法同步或调用 Call#enqueue 方法异步请求 HTTP。

List<Repo> repos = repoCall.execute().body();

请求返回的数据直接转化成了 List<Repo>,非常方便。

如果要使用 RxJava,在创建 Retrofit 对象时要调用
addCallAdapterFactory(RxJavaCallAdapterFactory.create()),则返回类型会从
Call<T> 转换成 Observable<T>

  1. 调用方法,请求实际的网络请求

通过以上三步,可以将服务器返回的json格式数据,转换为List<Repo>。

2. Retrofit

是不是非常的简单和清晰?我们似乎只写了一个GitHubService接口,定义了一个listRepos方法并加了一些注解,然后使用Retrofitcreate方法拿到GitHubService实例service,再调用listRepos方法就拿到了我们想要的数据。

2.1 build

先看一下 Retrofit.Builder 类里的成员变量。

private Platform platform;
private okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
private List<Converter.Factory> converterFactories = new ArrayList<>();
private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
private Executor callbackExecutor;
private boolean validateEagerly;

Platform 提供了3个平台:Java8AndroidIOS,全都继承自
Platform,初始化时静态方法 Platform#findPlatform
会自动识别属于哪一个。

private static Platform findPlatform() {
    try {
        Class.forName("android.os.Build");
        if (Build.VERSION.SDK_INT != 0) {
            return new Android();
        }
    } catch (ClassNotFoundException ignored) {
    }
    try {
        Class.forName("java.util.Optional");
        return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    try {
        Class.forName("org.robovm.apple.foundation.NSObject");
        return new IOS();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
}

通过 Retrofit.Builder#clientRetrofit.Builder#callFactory
可以自定义 OkHttpClient

public Builder client(OkHttpClient client) {
    return callFactory(checkNotNull(client, "client == null"));
}

public Builder callFactory(okhttp3.Call.Factory factory) {
    this.callFactory = checkNotNull(factory, "factory == null");
    return this;
}

如果不指定 callFactory,则默认使用 OkHttpClient

okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
    callFactory = new OkHttpClient();
}

converterFactoriesadapterFactories
提供了2个工厂列表,用于用户自定义数据转换和类型转换,后面会详细说明。

最后调用 Retrofit.Builder#build 创建一个 Retrofit 对象。

public Retrofit build() {
    // ... configured values

    return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
}
 Call<MyResponse> call = networkInterface.listRepos(); call.enqueue(new Callback<MyResponse>() { //与OkHttp不同,异步请求会回调到主线程 @Override public void onResponse(Call<MyResponse> call, Response<MyResponse> response) { } @Override public void onFailure(Call<MyResponse> call, Throwable t) { } });

好奇心驱使我弄明白这一切的来龙去脉~

2.2 create

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
        eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, 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);
              }
              ServiceMethod serviceMethod = loadServiceMethod(method);
              OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
              return serviceMethod.callAdapter.adapt(okHttpCall);
          }
    });
}

首先调用 Utils.validateServiceInterface 去判断 service 是否是一个
Interface 且没有继承其他 Interface,否则抛非法参数异常。

static <T> void validateServiceInterface(Class<T> service) {
    if (!service.isInterface()) {
        throw new IllegalArgumentException("API declarations must be interfaces.");
    }
    if (service.getInterfaces().length > 0) {
        throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
    }
}

如果 validateEagerlytrue,则会调用 eagerlyValidateMethods
方法,会去预加载 service 中的所有方法,默认为 false

private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
        if (!platform.isDefaultMethod(method)) {
          loadServiceMethod(method);
        }
    }
}

然后就是通过动态代理生成 service。前两个 if 分支分别判断是否是
Object 的方法及 default 方法,后者除了 Java8 其他都是 false

再看 loadServiceMethod

ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
    synchronized (serviceMethodCache) {
        result = serviceMethodCache.get(method);
        if (result == null) {
            result = new ServiceMethod.Builder(this, method).build();
            serviceMethodCache.put(method, result);
        }
    }
    return result;
}

通过 serviceMethodCache 实现缓存机制,同一个 service
的同一个方法只会创建一次,生成 ServiceMethod 同时存入 Cache

ServiceMethod 和需要的参数生成一个 OkHttpCall 对象。然后用
CallAdapter 将生成的 OkHttpCall
转换为我们需要的返回类型,这个后面会说到。

奥门威尼斯网址 2Retrofit请求处理流程图.PNG

构建Retrofit
Step2
我们可以看出来Retrofit使用了建造者模式来创建,Retrofit有几个重要的属性

3. ServiceMethod

Adapts an invocation of an interface method into an HTTP call.

ServiceMethod 的作用就是把一个 API 方法转换为一个 HTTP 调用。

Retrofit#loadServiceMethod 方法中可以看出一个 API 方法对应一个
ServiceMethod

GitHubService为例

public interface GitHubService {
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
}

@GET("users/{user}/repos")
MethodAnnotations@Path("user") String user
ParameterAnnotationsCall<List<Repo>>CallAdapter

说明:
Retrofit只存在一个CallFactory,但是存在多个CallAdapterFactory和ConvertFactory,针对不同的请求接口方法,Retrofit会通过其返回值,选择特定的CallAdapterFactory和CovertFactory。

public final class Retrofit {
  // ServiceMethod缓存,ServiceMethod其实是封装了调用listRepos时,请求的所有信息(请求方法GET、请求参数名称和值、请求地址等)
  private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();

  // 发起网络请求库
  private final okhttp3.Call.Factory callFactory; // 默认是OkHttpClient
  private final HttpUrl baseUrl; // 请求地址,不能为空
  private final List<Converter.Factory> converterFactories; // 转换器的工厂集合
  private final List<CallAdapter.Factory> adapterFactories; // 将返回结果包装成默认的Call<?>或者RxJava的Observable(默认内置ExecutorCallAdapterFactory)
  private final Executor callbackExecutor; // 负责控制回调结果所在的线程,Android默认是在主线程(MainThreadExecutor)
  ...
}

3.1 ServiceMethod.Builder

先看下 ServiceMethod.Builder 的构造函数

public Builder(Retrofit retrofit, Method method) {
    this.retrofit = retrofit;
    this.method = method;
    this.methodAnnotations = method.getAnnotations();
    this.parameterTypes = method.getGenericParameterTypes();
    this.parameterAnnotationsArray = method.getParameterAnnotations(); 
}

传入 retrofitmethod 对象,通过 method 获取到方法注解
methodAnnotations、参数类型 parameterTypes 和参数注解
parameterAnnotationsArrayparameterAnnotationsArray是一个二维数组
Annotation[][],因为一个参数可以有多个注解。

关键看 ServiceMethod.Builder#build 方法,会生成一个 ServiceMethod
对象,接下来按顺序解析。

4.1 Retrofit创建过程

通过前面基本的使用代码可以看出,Retrofit的创建也是采用Builder设计模式,通过new
Retrofit.Builder。我们先看看new Retrofit.Builder()的初始化工作。

public static final class Builder { ... public Builder() { this(Platform.get; } Builder(Platform platform) { converterFactories.add(new BuiltInConverters; } ...}

通过Platform.get()获取当前平台对象Platform,然后调用它的另一个构造器,在这个构造器中,为ConvertFactory集合添加一个默认的ConvertFactory,不同的ConvertFactory产生的Convert对OkHttp网络请求返回的Response转化处理不一样,而默认ConvertFactory的Convert并没有对Response做太多处理,获得的数据依旧是Response对象。通过Builder.addConverterFactory添加更多的ConvertFactory,比如xxx替换为GsonConverterFactory.create()添加GsonConvertFatory,它产生的GsonConvert就能将Response映射成JavaBean实体。

回到主流程,还是看看Platform.get()是如何处理的吧!

class Platform { private static final Platform PLATFORM = findPlatform(); // 静态工厂模式! static Platform get() { return PLATFORM; } private static Platform findPlatform() { // 识别当前平台,如果是Android,就直接返回Android()对象实例 try { Class.forName("android.os.Build"); if (Build.VERSION.SDK_INT != 0) { return new Android(); } } catch (ClassNotFoundException ignored) { } ... static class Android extends Platform { // Platform的子类,Android平台对象类 @Override public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); } @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) { // 获取Android平台的默认CallAdapterFactory对象 if (callbackExecutor == null) throw new AssertionError(); return new ExecutorCallAdapterFactory(callbackExecutor); } static class MainThreadExecutor implements Executor { // 获取Android平台的默认线程执行调度器,其实就是通过Handler用于线程切换。 private final Handler handler = new Handler(Looper.getMainLooper; @Override public void execute(Runnable r) { handler.post; } } } }

总结: 通过new
Retrofit.Builder()为ConvertFactory集合中添加一个默认ConvertFactory,创建一个包含默认的CallAdapterFactory、Executor的Android平台对象。注意,默认的ConvertFactory已经添加到了ConvertFactory集合中了,但是Android对象中的CallAdapterFactory并没有加入到CallAdapterFactory集合中。

接着看new Retrofit.Builder中的build()方法:

public Retrofit build() { if (baseUrl == null) { // 强制需要通过.baseUrl配置url throw new IllegalStateException("Base URL required."); } okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); // 创建CallFactory用于生产Call对象,从这里也可以看出Retrofit最终还是通过OkHttp发送网络请求 } Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); // 获取Android平台对象中的默认Executor,里面通过Handler进行线程切换,上面有讲过! } List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories); // 此处将Android平台对象中的CallAdapterFactory添加到Retrofit的CallAdapterFactory集合中. // 注意同时将Executor也传入到这个CallAdapterFactory中,那么工厂生产出来的CallAdapter就也就具有线程切换的能力。 adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories); return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); // 通过Builder创建Retrofit,并将配置参数作为参数传入 }

再看看一下Retrofit的构造:

 Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl, List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories, @Nullable Executor callbackExecutor, boolean validateEagerly) { this.callFactory = callFactory; this.baseUrl = baseUrl; this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site. this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site. this.callbackExecutor = callbackExecutor; this.validateEagerly = validateEagerly; }

以上这些属性会在Retrofit.Builder的build方法中去设置,其中会有些默认的属性

3.2 createCallAdapter

callAdapter = createCallAdapter() 会遍历 adapterFactories,通过 API
方法的 annotationsreturnType 取到第一个符合条件的
CallAdapter

for (int i = start, count = adapterFactories.size(); i < count; i++) {
    CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
    if (adapter != null) {
        return adapter;
    }
}

然后取到 responseType = callAdapter.responseType() 并进行判断,如果是
retrofit2.Response<T>okhttp3.Response
则抛异常,目前支持的有默认的 retrofit2.Call<T>,RxJava 的
rx.Observable,Java8 的 java.util.concurrent.CompletableFuture
Guava 的 com.google.common.util.concurrent.ListenableFuture

4.2 核心动态代理代码

NetworkInterface networkInterface =
retrofit.create(NetworkInterface.class);

public <T> T create(final Class<T> service) { Utils.validateServiceInterface; // 1. 判断网络请求接口类的合法性 if (validateEagerly) { // 2. 是否需要提前对 网络请求接口类 中的方法进行提前处理,即为接口中的每一个方法提前处理成 SeviceMethod对象,并缓存。 eagerlyValidateMethods; } // 3. 生成动态代理类 return  Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { private final Platform platform = Platform.get(); @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { ... // 4. 将接口中的方法处理成serviceMethod。 ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod; OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); // 5. 创建 OkHttpCall对象,传入serviceMethod对象和调用方法实际参数。 return serviceMethod.callAdapter.adapt(okHttpCall); // 6. 将Call对象进行CallAdapter进行转化( 比如RxCallAdapter将Call转化为Observable ) 注意Call还没有被执行,即没有进行网络请求。 } }); }

总结: retrofit.create方法中处理分三步:

    1. 判断网络请求接口类的合法性
    1. 是否需要提前对 网络请求接口类 中的方法进行预处理
    1. 返回生成动态代理类

调用网络请求接口方法,动态代理类中的invoke()方法被执行,也处理也分三步:

    1. 将对应的执行方法转化成ServiceMethod对象
    1. 创建OkHttpCall对象
  • 3 OkHttpCall通过CallAdapter进行Call的转化

public static final class Builder {
  // ...
  Builder(Platform platform) {
    this.platform = platform;
    // Add the built-in converter factory first. This prevents overriding its behavior but also
    // ensures correct behavior when using converters that consume all types.
    converterFactories.add(new BuiltInConverters());
  }
  // ...
  public Retrofit build() {
    if (baseUrl == null) {
      throw new IllegalStateException("Base URL required.");
    }

    okhttp3.Call.Factory callFactory = this.callFactory;
    if (callFactory == null) {
      callFactory = new OkHttpClient();
    }

    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {
      callbackExecutor = platform.defaultCallbackExecutor();
    }

    // Make a defensive copy of the adapters and add the default Call adapter.
    List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
    adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

    // Make a defensive copy of the converters.
    List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

    return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
      callbackExecutor, validateEagerly);
  }
}

3.3 createResponseConverter

responseConverter = createResponseConverter() 会遍历
converterFactories,通过 API 方法的 annotationsresponseType
取到第一个符合条件的 Converter<ResponseBody, T>

for (int i = start, count = converterFactories.size(); i < count; i++) {
    Converter<ResponseBody, ?> converter =
        converterFactories.get(i).responseBodyConverter(type, annotations, this);
    if (converter != null) {
        return (Converter<ResponseBody, T>) converter;
    }
}
4.3 调用接口方法

Call<MyResponse> call = networkInterface.listRepos();

在通过上面的说明,当调用网络请求接口类方法时,就会调用invoke方法,传入通过反射获取Method和执行方法参数args,因为没有调用call.execute()或call.enqueue,所以Call并没有执行。接下来我们具体看看invoke方法体中三部曲吧!

    1. 将对应的执行方法转化成ServiceMethod对象

 ServiceMethod<?, ?> loadServiceMethod(Method method) { ServiceMethod<?, ?> result = serviceMethodCache.get; // 先从缓存中取,如果在之前分析的create()中validateEagerly = true 必然从缓存中能取到。 if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get; if (result == null) { result = new ServiceMethod.Builder<>(this, method).build(); // 根据Method创建ServiceMethod对象 serviceMethodCache.put(method, result); // 将创建的ServiceMethod进行缓存 } } return result; }

接下来看看,ServiceMethod的创建!

ServiceMethodBuilder.class

 Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; // 1. 将外观类 Retrofit传入 this.method = method; this.methodAnnotations = method.getAnnotations(); // 2. 获取方法上的注解(@GET @POST... ) this.parameterTypes = method.getGenericParameterTypes(); this.parameterAnnotationsArray = method.getParameterAnnotations(); // 3. 获取参数注解(@Query ...) }public ServiceMethod build() { callAdapter = createCallAdapter(); // 4. 获取该方法对应的CallAdapter responseType = callAdapter.responseType(); // 5. 获取该方法的响应类型,比如Response或者自定义的JavaBean ... responseConverter = createResponseConverter(); // 6. 根据上面获取的响应类型获取对应的Convert for (Annotation annotation : methodAnnotations) { // 7. 解析第二步得到的方法注解 parseMethodAnnotation(annotation); } ... int parameterCount = parameterAnnotationsArray.length; parameterHandlers = new ParameterHandler<?>[parameterCount]; for (int p = 0; p < parameterCount; p++) { Type parameterType = parameterTypes[p]; ... Annotation[] parameterAnnotations = parameterAnnotationsArray[p]; // 8. 解析第三步得到的参数注解 ... parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations); } return new ServiceMethod<>; // 创建ServiceMethod对象 }

之前有说过Retrofit中可以有多个ConvertFactory和CallAdapterFactory,通过上面的第4步和第6步获取该Method对应的ConvertFactory和CallAdapterFactory。这两种Factory的适配过程近乎一样,所以这里只做CallAdapterFactory的配对过程。

private CallAdapter<T, R> createCallAdapter() { Type returnType = method.getGenericReturnType(); ... Annotation[] annotations = method.getAnnotations(); ... return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations); }

Retrofit.class

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { // type: return 返回的类型,比如Call、Observable ... int start = adapterFactories.indexOf + 1; // 用于做CallAdapterFactory跳过处理,默认start = 0 for (int i = start, count = adapterFactories.size(); i < count; i++) { CallAdapter<?, ?> adapter = adapterFactories.get.get(returnType, annotations, this); if (adapter != null) { return adapter; } } ...}

每一个CallAdapterFactory需要实现一个get(returnType,xxx)方法,如果能处理这个returnType就返回对应的CallAdapter对象。比如默认returnType为Call,那么就被默认的CallAdapterFactory接受处理,这个CallAdapterFactory在Android平台类中defaultCallAdapterFactory()获得(4.1
Retrofit创建过程 有说明)

Android.class

@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) { if (callbackExecutor == null) throw new AssertionError(); return new ExecutorCallAdapterFactory(callbackExecutor); }

ExecutorCallAdapterFactory.class

final class ExecutorCallAdapterFactory extends CallAdapter.Factory { final Executor callbackExecutor; ExecutorCallAdapterFactory(Executor callbackExecutor) { this.callbackExecutor = callbackExecutor; } @Override public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) != Call.class) { return null; } final Type responseType = Utils.getCallResponseType(returnType); return new CallAdapter<Object, Call<?>>() { @Override public Type responseType() { return responseType; } @Override public Call<Object> adapt(Call<Object> call) { return new ExecutorCallbackCall<>(callbackExecutor, call); } }; }

总结:
ServiceMethod通过Builder模式创建,包含了Retrofit对象,对执行的Method进行剖析,像方法注解、参数注解、参数类型、CallAdapter、ConvertAdapter,所以一个ServiceMethod对象包含了网络请求需要的所有信息。

    1. 创建OkHttpCall对象

OkHttpCall<Object> okHttpCall = new
OkHttpCall<>(serviceMethod, args);

OkHttpCall.class

 OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) { this.serviceMethod = serviceMethod; this.args = args; }
  • 3 OkHttpCall通过CallAdapter进行Call的转化

serviceMethod.callAdapter.adapt(okHttpCall);

如果接口方法返回类型是Call的话,CallAdapter就是默认的CallAdaterFactory创建的CallAdapter,即ExecutorCallAdapterFactory类中get()方法返回的CallAdapter:

new CallAdapter<Object, Call<?>>() { @Override public Type responseType() { return responseType; } @Override public Call<Object> adapt(Call<Object> call) { return new ExecutorCallbackCall<>(callbackExecutor, call); } };

接着定位返回的CallAdapter中adapt()方法,最后返回了一个new
ExecutorCallbackCall<>(callbackExecutor, call);
对象,代表serviceMethod.callAdapter.adapt(okHttpCall);的执行结束,并向外暴露一个ExecutorCallbackCall对象。

    1. 同步异步网络请求

// 同步请求call.execute();// 异步请求call.enqueue(new Callback<MyResponse>() { //与OkHttp不同,异步请求会回调到主线程 @Override public void onResponse(Call<MyResponse> call, Response<MyResponse> response) { } @Override public void onFailure(Call<MyResponse> call, Throwable t) { } });

与同步相比,异步相对来说复杂一点点,这里只分析异步,相信异步看懂了,同步肯定不在话下。

ExecutorCallbackCall.class

@Override public void enqueue(final Callback<T> callback) { ... delegate.enqueue(new Callback<T>() { // delegate是由serviceMethod.callAdapter.adapt(okHttpCall); 传入的,所以最终的网络请求还是通过OkHttpCall进行。 @Override public void onResponse(Call<T> call, final Response<T> response) { callbackExecutor.execute(new Runnable() { // callbackExecutor 是Android平台对象类中的MainThreadExecutor 主要将线程切换到主线程 @Override public void run() { if (delegate.isCanceled { ... } else { callback.onResponse(ExecutorCallbackCall.this, response); } } }); } @Override public void onFailure(Call<T> call, final Throwable t) { callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(ExecutorCallbackCall.this, t); } }); } }); }

OkHttpCall.class

@Override public void enqueue(final Callback<T> callback) { ... call.enqueue(new okhttp3.Callback() { // 这个Call才是OKHttp中正宗的Call @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) throws IOException { Response<T> response; try { response = parseResponse(rawResponse); } catch (Throwable e) { callFailure; return; } callSuccess; } ... }
  • Builder模式
  • 外观模式
  • 静态工厂模式
  • 动态工厂模式
  • 适配器模式
  • 动态代理模式
  1. baseUrl如果为空会抛出异常“Base URL
    required”,所以这个参数不能为空。

  2. callFactory如果不指定,则使用默认的OkHttpClient来作为网络库。

  3. callbackExecutor如果为空,会根据不同平台Platform来设置,Android默认用的是下面这个MainThreadExecutor。它的作用就是线程调度器,会控制最终回调结果所在的线程。

  4. adapterFactories首先会添加我们自定义的适配器工厂,然后会加上系统内置的ExecutorCallAdapterFactory。这与第三点是一致的,都是根据不同平台来设置,Android平台如下:

    static class Android extends Platform {
     @Override public Executor defaultCallbackExecutor() {
       return new MainThreadExecutor();
     }
    
     @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
       return new ExecutorCallAdapterFactory(callbackExecutor);
     }
    
     static class MainThreadExecutor implements Executor {
       private final Handler handler = new Handler(Looper.getMainLooper());
    
       @Override public void execute(Runnable r) {
         handler.post(r);
       }
     }
    }
    

3.4 parseMethodAnnotation

for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);
}

遍历 API 方法的所有 annotations,如实例中的
@GET("users/{user}/repos"),根据所属类型和值解析成 HTTP
请求需要的数据。

在 package retrofit2.http 下包含了所有的 Method Annotation
Parameter Anootation

DELETEGETHEADPATHCPOSTPUTOPTIONSHTTP
类型的 annotaion 会调用 parseHttpMethodAndPath,生成
httpMethodhasBodyrelativeUrlrelativeUrlParamNames

retrofit2.http.Headers 类型的 annotaion 会调用 parseHeaders,生成
headers

MultipartFormUrlEncoded 类型的 annotaion 分别生成
isMultipartisFormEncoded,两者互斥,不能同时为
true,否则会抛异常。

然后对生成的部分参数检查,httpMethod 不能为空,如果 hasBody
false,则 isMultipartisFormEncoded 必须也为
false,否则会抛异常。

if (httpMethod == null) {
    throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}

if (!hasBody) {
    if (isMultipart) {
        throw methodError(
            "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
    }
    if (isFormEncoded) {
        throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
            + "request body (e.g., @POST).");
    }
}

adapterFactories集合中的CallAdapter.Factory是一个非常重要的概念,它会将请求的对象转换为Call<?>(默认,然后使用enqueue执行异步);如果你使用了RxJava,它会转换为Observable,你可以使用RxJava的链式调用来处理请求与响应。

3.5 parseParameterAnnotation

int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
    ...  
    Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}

遍历每个参数的 parameterAnnotations,如实例中的
@Path("user") String user,根据所属类型和值解析成对应的
ParameterHandler,每个 Parameter Anootation 类型都有对应的
ParameterHandler,且每个参数只能有一个 ParameterHandler

可以看下 parseParameter 的逻辑

private ParameterHandler<?> parseParameter(
        int p, Type parameterType, Annotation[] annotations) {
    ParameterHandler<?> result = null;
    for (Annotation annotation : annotations) {
        ParameterHandler<?> annotationAction = parseParameterAnnotation(
            p, parameterType, annotations, annotation);

        if (annotationAction == null) {
            continue;
        }

        if (result != null) {
            throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
        }

        result = annotationAction;
    }

    if (result == null) {
        throw parameterError(p, "No Retrofit annotation found.");
    }

    return result;
}

关键在 parseParameterAnnotation,根据 annotation
的类型并做参数校验,会生成不同的 ParameterHandler,如 RelativeUrl

if (type == HttpUrl.class
    || type == String.class
    || type == URI.class
    || (type instanceof Class && "android.net.Uri".equals(((Class<?>) type).getName()))) {
    return new ParameterHandler.RelativeUrl();
} else {
    throw parameterError(p, "@Url must be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri type.");
}

由于 Retrofit 不依赖 Android SDK,判断 type 时无法获取到
android.net.Uri.class,因此采用了
"android.net.Uri".equals(((Class<?>) type).getName()) 的技巧。

每个 Parameter Anootation 都会对应一个 ParameterHandler,如
static final class Path<T> extends ParameterHandler<T>,它们都实现了
ParameterHandler<T>

ParameterAnnotation ? extends ParameterHandler
Url RelativeUrl
Path Path
Query Query
QueryMap QueryMap
Header Header
HeaderMap HeaderMap
Field Field
FieldMap FieldMap
Part Part
PartMap PartMap
Body Body

每种 ParameterHandler 都通过 Converter<F, T> 将我们的传参类型转化成
RequestBuilder 需要的类型,并设置其参数。举个例子

static final class Query<T> extends ParameterHandler<T> {
    private final String name;
    private final Converter<T, String> valueConverter;
    private final boolean encoded;

    Query(String name, Converter<T, String> valueConverter, boolean encoded) {
        this.name = checkNotNull(name, "name == null");
        this.valueConverter = valueConverter;
        this.encoded = encoded;
    }

    @Override void apply(RequestBuilder builder, T value) throws IOException {
        if (value == null) return; // Skip null values.
        builder.addQueryParam(name, valueConverter.convert(value), encoded);
    }
}

valueConverter.convert 将我们的传参类型 T 转换成 String,并设置到
RequestBuilder 中。其他的配置也是按同样的方式。

CallAdapter.Factory有时间会继续做进一步的讲解~

4. OkHttpCall

OkHttpCall 实现了 retrofit2.Call<T>,看下它的构造函数,传入
ServiceMethod 和请求参数。

OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
}
  1. converterFactories集合用来存储转换器工厂,在Retrofit.Builder的构造函数中,会添加默认的BuiltInConverters。Converter.Factory的作用有两个:

    public interface Converter<F, T> {
       T convert(F value) throws IOException;
       abstract class Factory {
         // 响应数据转换为ResponseBody
         public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
           return null;
         }
    
         // 请求数据转换为RequestBody,常用于body
         public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
           return null;
         }
    
         // 请求数据转换为String,常用于Header、Field、Query
         public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
           return null;
         }
       }
    }
    

4.1 createRawCall

先看下 OkHttpCall#createRawCall

private okhttp3.Call createRawCall() throws IOException {
    Request request = serviceMethod.toRequest(args);
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
        throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
}

将已经生成的 serviceMethod 通过 toRequest(args) 转成一个
okhttp3.Request 对象。再用创建 Retrofit 时指定的
okhttp3.Call.Factory 创建一个 okhttp3.Call,这里如果不指定
okhttp3.Call.Factory,则默认是 okhttp3.OkHttpClient

ServiceMethod#toRequest 方法中,用 method 相关的配置生成一个
retrofit2.RequestBuilder 后,再用之前准备好的 parameterHandlers
处理每一个参数,最后生成一个 okhttp3.Request

/** Builds an HTTP request from method arguments. */
Request toRequest(Object... args) throws IOException {
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody, isFormEncoded, isMultipart);

    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

    // ... 校验

    for (int p = 0; p < argumentCount; p++) {
        handlers[p].apply(requestBuilder, args[p]);
    }

    return requestBuilder.build();
}
  • RequestBody包含了contentType、contentLength以及“请求数据”等。
  • ResponseBody包含了contentType、contentLength以及“响应数据”等。

4.2 execute

okhttp3.Call#execute 用于同步请求
HTTP,线程会被阻塞,请求成功后返回我们指定的数据类型。

@Override public Response<T> execute() throws IOException {
    okhttp3.Call call;

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

        if (creationFailure != null) {
            if (creationFailure instanceof IOException) {
                throw (IOException) creationFailure;
            } else {
                throw (RuntimeException) creationFailure;
            }
        }

        call = rawCall;
        if (call == null) {
            try {
                call = rawCall = createRawCall();
            } catch (IOException | RuntimeException e) {
                creationFailure = e;
                throw e;
            }
        }
    }

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

    return parseResponse(call.execute());
}

首先检查 okhttp3.Call 是否已被执行。

一个 okhttp3.Call 只能被执行一次,可以调用 OkHttpCall#clone
重新创建一个新的相同配置的 HTTP 请求。

@Override public OkHttpCall<T> clone() {
    return new OkHttpCall<>(serviceMethod, args);
}

然后检查并创建 okhttp3.Call,调用 okhttp3.Call#execute
执行同步请求。

最后调用 parsePesponse 将返回的 okhttp3.Response
解析成我们需要的数据。

Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    // Remove the body's source (the only stateful object) so we can pass the response along.
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    int code = rawResponse.code();
    // ... 状态码检查

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
        T body = serviceMethod.toResponse(catchingBody);
        return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
        // If the underlying source threw an exception, propagate that rather than indicating it was
        // a runtime exception.
        catchingBody.throwIfCaught();
        throw e;
    }
}

okhttp3.Response 进行一些状态码检查后调用
ServiceMethod#toResponse
生成我们需要的数据类型。这里就用到了我们之前准备好的
responseConverter。最后封装成一个
retrofit2.Response<T>,包含了原始的 rawResponse、我们需要的 body
errorBody,我们取需要的数据。

如果你使用了GsonConverterFactory,那么看起来是这样的

4.3 enqueue

okhttp3.Call#enqueueokhttp3.Call#execute 流程类似,异步请求
HTTP,然后将回调都交给 retrofit2.Callback<T> 处理。

看下 retrofit2.Callback#onFailure 的注释

Invoked when a network exception occurred talking to the server or
when an unexpected exception occurred creating the request or
processing the response.

这里 retrofit2.Callback#onFailure
除了处理网络异常外,还会处理创建网络请求和解析数据的异常,在回调中处理,而不是直接
crash,这点做的非常好。

  1. createRawCall 抛出的异常

    try {
        call = rawCall = createRawCall();
    } catch (Throwable t) {
        failure = creationFailure = t;
    }
    

    如果出异常,直接回调,不执行接下来 enqueue 方法。

  2. 执行 okhttp3.Call#enqueueokhttp3.Callback 抛出的网络请求异常

  3. 网络请求成功后在 okhttp3.Callback#onResponseparseResponse
    时抛出的异常

    try {
        response = parseResponse(rawResponse);
    } catch (Throwable e) {
        callFailure(e);
        return;
    }
    
  4. CallAdapter

前面已经简单介绍过 ServiceMethod#createCallAdapter,它会从
adapterFactories 中找到第一个符合条件的 CallAdapter.Factory

    public final class GsonConverterFactory extends Converter.Factory {
      // ...
      @Override
      public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
          Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new GsonResponseBodyConverter<>(gson, adapter);
      }
      // ...
    }

5.1 retrofit-adapters

先来看 Retrofit 提供的 retrofit-adapters 模块,目前供我们选择使用的有
guavajava8rxjava,分别对应的 CallAdapter.Factory
GuavaCallAdapterFactoryJava8CallAdapterFactory
RxJavaCallAdapterFactory

Retrofit#build 时,除了我们自己添加的 CallAdapter.Factory
还会添加两个默认的 CallAdapter.FactoryExecutorCallAdapterFactory
DefaultCallAdapterFactory

// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

Retrofit 源码中有大量类似
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
的例子,不直接使用成员变量,而是将成员变量重新拷贝给一个新的临时变量,这样虽然多申请了4个字节内存,但如果以后将成员变量改成入参,就可以不用改代码直接使用了,是一种好的编码习惯。

返回的GsonResponseBodyConverter,最终会使用convert方法,将服务器返回的数据转换为方法的返回类型

5.2 default

再看默认的 CallAdapter.Factory

CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
    if (callbackExecutor != null) {
        return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    return DefaultCallAdapterFactory.INSTANCE;
}

DefaultCallAdapterFactoryExecutorCallAdapterFactory
返回的类型都是 retrofit2.Call<R>

DefaultCallAdapterFactory 中,CallAdapter#adapt
什么都不做,直接返回 retrofit2.Call<R>。而
ExecutorCallAdapterFactoryCallAdapter#adapt 则返回
ExecutorCallbackCall<T>,它实现了 retrofit2.Call<R>,会传入一个
Executor,同步调用不变,异步调用时会在指定的 Executor 上执行。

   final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
      private final TypeAdapter<T> adapter; // Call<T>或者Observable<T>中的T的转换适配器
      // ...

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

5.3 adapt

看下 CallAdapteradapt 方法

/**
  * Returns an instance of {@code T} which delegates to {@code call}.
  */
<R> T adapt(Call<R> call);

它的作用就是把 retrofit2.Call<R> 转换成我们需要的 T

CallAdapters ? extends CallAdapter.Factory T
guava retrofit2.adapter.guava.GuavaCallAdapterFactory com.google.common.util.concurrent.ListenableFuture
java8 retrofit2.adapter.java8.Java8CallAdapterFactory java.util.concurrent.CompletableFuture
rxjava retrofit2.adapter.rxjava.RxJavaCallAdapterFactory rx.Observable
default retrofit2.ExecutorCallAdapterFactory retrofit2.Call<R>
default retrofit2.DefaultCallAdapterFactory retrofit2.Call<R>

List<CallAdapter.Factory> 中添加的顺序是我们指定的一个或多个
CallAdapter.Factory,默认的 ExecutorCallAdapterFactory
DefaultCallAdapterFactory,查找时按顺序查找。

我们已经分析完了Retrofit以及内部几个重要属性的创建过程,并且介绍了属性的很多关键方法的作用。接下来,我们介绍Retrofit是如何使用这些属性完成我们的工作的。

6. Converter

Converter 的作用就是将 HTTP
请求返回的数据格式转换成我们需要的对象,或将我们提供的对象转换成 HTTP
请求需要的数据格式。

public interface Converter<F, T> {
    T convert(F value) throws IOException;
}

接口非常清晰,将 F 转换成 T


6.1 Factory

来看 Converter.Factory

abstract class Factory {
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return null;
    }

    public Converter<?, RequestBody> requestBodyConverter(Type type,
        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return null;
    }

    public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return null;
    }
}
  1. responseBodyConverter 用于将 HTTP 请求返回的 response
    转换成我们指定的类型。
  2. requestBodyConverter 用于将 BodyPartPartMap
    3种类型的参数转换成 HTTP 的请求体。
  3. stringConverter 用于将
    FieldFieldMapHeaderPathQueryQueryMap
    这几种类型的参数转换成 String

构建Retrofit Service
Step2中,创建完Retrofit后,我们通过以下代码获得GitHubService的对象service

6.2 retrofit-converters

CallAdapter 类似,Retrofit 也提供了默认的
Converter.Factory——BuiltInConverters,只能处理基本的
ResponseBodyRequestBodyString 类型。

在 Retrofit 提供的 retrofit-converters 模块,供我们选择的有
GsonJacksonMoshiProtocol BuffersXMLScalar
Wire,我们常用的有 GsonConverterFactory

需要注意的是,Jake
Wharton
在他的一篇演讲 Simple HTTP with Retrofit
2
中说道

I want to stress that the order matters. This is the order in which
we’re going to ask each one whether or not it can handle a type. What
I have written above is actually wrong. If we ever specify a proto,
it’s going to be encoded as JSON, which will try and deserialize the
response buddy as JSON. That’s obviously not what we want. We will
have to flip these because we want to check protocol buffers first,
and then JSON through GSON.

说的就是 Retrofit.Builder#addConverterFactory 的顺序非常重要,先添加的
Converter.Factory 会先用来解析,而 Gson 非常强大,如果第一个添加
GsonConverterFactory,则其他想要转换的类型如 Protocol Buffers
就不会执行,因此建议将 GsonConverterFactory 作为最后一个添加

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

7. 总结

Retrofit
的源码还是很难的,反反复复看了很多遍,除了其原理和流程外,从中也学到了一些技巧和设计模式。在写这篇文章的同时又把思路和流程重新理了一遍,对自己帮助还是非常大的。关于源码最大的感受就是各个类之间传对象调用感觉非常乱,也增加了理解的难度,如
RetrofitServiceMethod 之间就互相依赖。

本文是 慌不要慌
原创,发表于
https://danke77.github.io/,请阅读原文支持原创
https://danke77.github.io/2016/08/06/retrofit-source-analysis/,版权归作者所有,转载请注明出处。

传入GitHubService的Class就能返回一个GitHubService对象,有这么玄乎的事情?我们看下是如何实现的:

public <T> T create(final Class<T> service) {
  // ...省略
  return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
      new InvocationHandler() {
        private final Platform platform = Platform.get();

        @Override public Object invoke(Object proxy, Method method, Object... args)
          throws Throwable {
          // ...省略
          ServiceMethod serviceMethod = loadServiceMethod(method);
          OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
          return serviceMethod.callAdapter.adapt(okHttpCall);
        }
      });
}

看到Proxy、InvocationHandler,熟悉Java动态代理的同学,应该会豁然开朗~,如果不熟悉可以先看下这篇文章:公共技术点之
Java
动态代理。

省略次要的代码,invoke方法中剩下两个重要的类:

  • ServiceMethod
    封装了定义在GitHubService中某个方法的“要素”(参数名称、参数注解、方法注解),通俗点讲就是HTTP请求的地址、参数名称和值、方法等。
  • OkHttpCall
    代理类,内部使用okhttp3.Call来实现同步/异步的请求。

我们逐个击破,先看下ServiceMethod的创建过程:

ServiceMethod loadServiceMethod(Method method) {
  ServiceMethod result;
  synchronized (serviceMethodCache) {
    result = serviceMethodCache.get(method);
    if (result == null) {
      result = new ServiceMethod.Builder(this, method).build();
      serviceMethodCache.put(method, result);
    }
  }
  return result;
}

主要就是用了一个缓存,同一个Method只会创建一个ServiceMethod对象。
我们重点看下ServiceMethod的创建过程,它也是用的建造者模式

final class ServiceMethod<T> {
  // ...省略
  static final class Builder<T> {
    final Annotation[] methodAnnotations; // 方法注解
    final Annotation[][] parameterAnnotationsArray; // 参数注解
    final Type[] parameterTypes; // 参数类型
    Type responseType; // 返回
    Converter<ResponseBody, T> responseConverter; // Converter.Factory的responseBodyConverter方法返回的对象
    CallAdapter<?> callAdapter; // CallAdapter.Factory的get方法返回对象

    public Builder(Retrofit retrofit, Method method) {
      // ...省略
      this.methodAnnotations = method.getAnnotations();
      this.parameterTypes = method.getGenericParameterTypes();
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

    public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      // ...省略
      responseConverter = createResponseConverter();

      // ...解析方法注解,url、header、post/get/put..
      // ...解析参数注解
      return new ServiceMethod<>(this);
    }
  }
}

我们重点看下build方法:

  1. callAdapter是根据ServiceMethod(Method的注解、返回类型),从RetrofitadapterFactories集合中取出一个合适的工厂CallAdapter.Factory,然后使用get方法返回的:

    private CallAdapter<?> createCallAdapter() {
      Type returnType = method.getGenericReturnType();
      // ...省略
      Annotation[] annotations = method.getAnnotations();
      try {
        return retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }
    

我们看到,实际上是调用retrofit.callAdapter(returnType, annotations)

   public final class Retrofit {
      // ...省略
      public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
        return nextCallAdapter(null, returnType, annotations);
      }

      public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
        // ...省略
        int start = adapterFactories.indexOf(skipPast) + 1;
        for (int i = start, count = adapterFactories.size(); i < count; i++) {
          CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
          if (adapter != null) {
            return adapter;
          }
        }
        // ...省略
      }
      // ...省略
   }

callAdapter会再调用nextCallAdapter方法,这个方法就是遍历adapterFactories,根据returnType(方法返回类型)和annotations(方法的注解),调用CallAdapter.Factoryget方法获得一个CallAdapter对象。

CallAdapter.Factory的直接继承子类有三种:

  • DefaultCallAdapterFactory
  • RxJavaCallAdapterFactory
  • ExecutorCallAdapterFactory

示例代码没有添加其他CallAdapter.Factory,且返回类型是Call<List<Repo>>,所以会用到Retrofit中的默认工厂:ExecutorCallAdapterFactory

为了不牵扯更多的知识(RxJava相关),我们这里只分析ExecutorCallAdapterFactory,有兴趣的同学可以去看下其他两个的实现。

重点看下ExecutorCallAdapterFactoryget方法:

   final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
      @Override
      public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        // ...省略
        return new CallAdapter<Call<?>>() {
          // ...省略
          @Override public <R> Call<R> adapt(Call<R> call) {
            return new ExecutorCallbackCall<>(callbackExecutor, call);
          }
        };
      }
   }

get方法返回的是CallAdapterCallAdapteradapt方法,正是我们在Retrofitcreate方法中最后调用的:

   // ...省略
   return serviceMethod.callAdapter.adapt(okHttpCall);

adapt返回的ExecutorCallbackCall是一个实现了Call接口的代理类,它的enqueueexecute等方法,最终调用的都是传入的参数okHttpCall(同样也实现了Call接口)的方法。

之所以这样设计,是为了控制enqueue方法返回的结果所在的线程,它使用了Retrofit在构建时的Executor属性来作为线程的调度器(还记得吧?Android中默认的是MainThreadExecutor。):

   static final class ExecutorCallbackCall<T> implements Call<T> {
      final Executor callbackExecutor;
      final Call<T> delegate;

      ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
        this.callbackExecutor = callbackExecutor;
        this.delegate = delegate;
      }

      @Override public void enqueue(final Callback<T> callback) {
        // ...
        delegate.enqueue(new Callback<T>() {
          @Override public void onResponse(Call<T> call, final Response<T> response) {
            callbackExecutor.execute(new Runnable() {
              @Override public void run() {        
                // ...        
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            });
          }
          // ...
        });
      }
   }

callbackExecutor就是MainThreadExecutorcallbackOkHttpCall。我们有理由相信OkHttpCall中大有玄妙,我们稍后会作分析~

  1. responseConverter是通过createResponseConverter()方法创建的:

    private Converter<ResponseBody, T> createResponseConverter() {
       Annotation[] annotations = method.getAnnotations();
       try {
         return retrofit.responseBodyConverter(responseType, annotations);
       } catch (RuntimeException e) { // Wide exception range because factories are user code.
         throw methodError(e, "Unable to create converter for %s", responseType);
       }
    }
    

我们发现调用了retrofitresponseBodyConverter方法:

   public final class Retrofit {
     // ...
     public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
       return nextResponseBodyConverter(null, type, annotations);
     }

     public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast, Type type, Annotation[] annotations) {
       // ...
       int start = converterFactories.indexOf(skipPast) + 1;
       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;
         }
       }
       // ...
     }
     // ...
   }

遍历converterFactories集合,调用Converter.FactoryresponseBodyConverter方法,返回一个Converter对象。如果你的接口返回数据是json格式,那么你会使用GsonConverterFactory来做为结果的转换器:

   public final class GsonConverterFactory extends Converter.Factory {
     // ...
     @Override
     public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
       TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
       return new GsonResponseBodyConverter<>(gson, adapter);
     }
   }

responseBodyConverter方法返回的GsonResponseBodyConverter是用来将json数据格式转换为T,它的方法很简单,关键方法就是convert

   final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private final Gson gson;
    private final TypeAdapter<T> adapter;

    GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
      this.gson = gson;
      this.adapter = adapter;
    }

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

主要就是使用Gson这个框架来做解析,这不是本文的重点,所以不做过多分析了。

至此,ServiceMethod我们已经分析完毕了。
接下来我们看下OkHttpCall吧~


OkHttpCall,让请求飞吧~

OkHttpCall实现了retrofit2.Call接口,实现了我们常用的异步请求enqueue、同步请求execute等方法,其实内部是使用okhttp3.Call来完成最终的网络请求,如果你还不熟悉OkHttp,可以参考这篇文章:
Android OkHttp完全解析
是时候来了解OkHttp了。

我们以同步方法execute做为示例分析下,enqueue其实是大同小异的:

@Override public Response<T> execute() throws IOException {
  okhttp3.Call call;
  // ...省略
  call = rawCall = createRawCall();
  // ...省略   
  return parseResponse(call.execute());
}

使用createRawCall创建call对象,然后调用call.execute的方法得到Response对象,看下okhttp3.Call的创建过程:

private okhttp3.Call createRawCall() throws IOException {
  Request request = serviceMethod.toRequest(args);
  okhttp3.Call call = serviceMethod.callFactory.newCall(request);
  if (call == null) {
    throw new NullPointerException("Call.Factory returned null.");
  }
  return call;
}

这里又看到ServiceMethod,使用toRequest方法,将ServiceMethod中保存的请求信息转换为Request对象,然后使用serviceMethod.callFactory.newCal方法,返回okhttp3.Call对象。我们之前分析过,callFactory实际就是Retrofit中的callFactory对象,而默认的callFactory使用的是OkHttpClient

接上文,得到Response对象,会调用parseReponse方法,最终得到Response<T>对象,T也就是我们在方法中定义的返回类型:

Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
  ResponseBody rawBody = rawResponse.body();
  // ...省略
  ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
  // ...省略
  T body = serviceMethod.toResponse(catchingBody);
  return Response.success(body, rawResponse);
}

我们比较关心T是如何生成的,所以看下serviceMethod.toResponse方法:

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

responseConverter实际就是GsonResponseBodyConverter,我们在分析ServiceMethod的时候提到过,其实就是用了Gson框架对发挥的json格式数据做了一个“反序列化”操作。

至此,我们已经分析完Retrofit的整个工作流程。


第一次尝试把源码分析的过程整理出来,因为篇幅比较长,所以阅读体验希望大家能多提提意见,您的意见正是我宝贵的财富,谢谢~

发表评论

电子邮件地址不会被公开。 必填项已用*标注