OkHttp源码 和 Retrofit源码 一起读

  平时有在用 OkHttp 和 Retrofit 两个框架,一时兴起想读一下源码顺便写篇博客。写得很长…很枯燥…emmmm……权当是自己的学习笔记吧。如果在此之外还能帮到也想了解这两个框架的朋友,那是最好不过了,哈哈。

OkHttp

  先来看一下 OkHttp 的最基础使用。

        // Step 1
        OkHttpClient okHttpClient = new OkHttpClient();
        // Step 2
        Request request = new Request.Builder()
                .url("http://www.baidu.com")
                .build();
        // Step 3 同步请求
        try {
            okhttp3.Response response = okHttpClient.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // Step 3 异步请求
        okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {
            @Override
            public void onFailure(okhttp3.Call call, IOException e) {

            }

            @Override
            public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {

            }
        });

  OkHttp最基础的使用分为三步,第一步创建 OkHttpClient,第二步创建一个 Request,最后一步就是请求,请求又分为同步请求和异步请求,我们从这个流程出发,读一下这个流程实现的源码。

创建 OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient();

  看一下它这个无参构造函数。

public OkHttpClient() {
    this(new Builder());
  }

  可以发现无参构造函数内部调用的是有一个 Builder 类型参数的构造函数。先看一下传入的 Builder 参数。这边传入的 Builder 参数,是用 new Builder() 创建了一个对象,来看看这个 new Builder() 是创建了一个怎样的对象。

    public Builder() {
      dispatcher = new Dispatcher();
      protocols = DEFAULT_PROTOCOLS;
      connectionSpecs = DEFAULT_CONNECTION_SPECS;
      eventListenerFactory = EventListener.factory(EventListener.NONE);
      proxySelector = ProxySelector.getDefault();
      cookieJar = CookieJar.NO_COOKIES;
      socketFactory = SocketFactory.getDefault();
      hostnameVerifier = OkHostnameVerifier.INSTANCE;
      certificatePinner = CertificatePinner.DEFAULT;
      proxyAuthenticator = Authenticator.NONE;
      authenticator = Authenticator.NONE;
      connectionPool = new ConnectionPool();
      dns = Dns.SYSTEM;
      followSslRedirects = true;
      followRedirects = true;
      retryOnConnectionFailure = true;
      connectTimeout = 10_000;
      readTimeout = 10_000;
      writeTimeout = 10_000;
      pingInterval = 0;
    }

  从 Builder 的构造方法中可以看出,它主要的工作是初始化一些值,此无参的 Builder 构造方法初始化的值采用的是默认的值。由 Builder 这个名字就可以知道,它是 Builder 模式的,可以用 Builder 模式的方式链式地自定义初始化各个参数,这里不予展开。当我们的 Builder 对象创建好时,就可以把它作为参数传给 OkHttpClient(Builder builder) 构造方法,构造 OkHttpClient 对象。

OkHttpClient(Builder builder) {
    this.dispatcher = builder.dispatcher;
    this.proxy = builder.proxy;
    this.protocols = builder.protocols;
    this.connectionSpecs = builder.connectionSpecs;
    this.interceptors = Util.immutableList(builder.interceptors);
    this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
    this.eventListenerFactory = builder.eventListenerFactory;
    this.proxySelector = builder.proxySelector;
    this.cookieJar = builder.cookieJar;
    this.cache = builder.cache;
    this.internalCache = builder.internalCache;
    this.socketFactory = builder.socketFactory;

    boolean isTLS = false;
    for (ConnectionSpec spec : connectionSpecs) {
      isTLS = isTLS || spec.isTls();
    }

    if (builder.sslSocketFactory != null || !isTLS) {
      this.sslSocketFactory = builder.sslSocketFactory;
      this.certificateChainCleaner = builder.certificateChainCleaner;
    } else {
      X509TrustManager trustManager = Util.platformTrustManager();
      this.sslSocketFactory = newSslSocketFactory(trustManager);
      this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
    }

    if (sslSocketFactory != null) {
      Platform.get().configureSslSocketFactory(sslSocketFactory);
    }

    this.hostnameVerifier = builder.hostnameVerifier;
    this.certificatePinner = builder.certificatePinner.withCertificateChainCleaner(
        certificateChainCleaner);
    this.proxyAuthenticator = builder.proxyAuthenticator;
    this.authenticator = builder.authenticator;
    this.connectionPool = builder.connectionPool;
    this.dns = builder.dns;
    this.followSslRedirects = builder.followSslRedirects;
    this.followRedirects = builder.followRedirects;
    this.retryOnConnectionFailure = builder.retryOnConnectionFailure;
    this.connectTimeout = builder.connectTimeout;
    this.readTimeout = builder.readTimeout;
    this.writeTimeout = builder.writeTimeout;
    this.pingInterval = builder.pingInterval;

    if (interceptors.contains(null)) {
      throw new IllegalStateException("Null interceptor: " + interceptors);
    }
    if (networkInterceptors.contains(null)) {
      throw new IllegalStateException("Null network interceptor: " + networkInterceptors);
    }
  }

  从这个构造函数中可以看出,它主要的工作就是把之前创建的 Builder 中的参数赋给 OkHttpClient 中的对象。到此,一个 OkHttpClient 对象就创建好了。

创建 Request
Request request = new Request.Builder()
                .url("http://www.baidu.com")
                .build();

  Request 采用的也是 Builder 模式,Request.Builder 是 Request 的内部类。通过 Builder 里的各种方法,设置各个参数。



  最后调用的 build() 方法,返回的是一个 Request 对象,将 Builder 对象本身作为参数传给 Request 构造函数。

    public Request build() {
      if (url == null) throw new IllegalStateException("url == null");
      return new Request(this);
    }

  看一下 Request 构造方法。

Request(Builder builder) {
    this.url = builder.url;
    this.method = builder.method;
    this.headers = builder.headers.build();
    this.body = builder.body;
    this.tags = Util.immutableMap(builder.tags);
  }

  很简单,就是将 Builder 对象中设置好的参数赋给 Requset 对象。
  创建 OkHttpClient 和 Request 对象的两个步骤都不复杂,主要是一些参数的初始化与赋值,OkHttp 关键的就是下面的请求部分。

请求部分

  先拿同步请求来讲。

        try {
            okhttp3.Response response = okHttpClient.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }

  请求先调用了 okHttpClient 的 newCall 方法,并将之前创建的 request 作为参数传入。看一下这个 newCall 方法做了什么操作。

  /**
   * Prepares the {@code request} to be executed at some point in the future.
   */
  @Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }

  可以看到它并没有做什么操作,而是调用了 RealCall.newRealCall 方法,并将 okHttpClient (this), request 对象作为参数传入,false 表示与 Socket 不相关。我们继续看一下 RealCall.newRealCall方法。

  static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
  }

  newRealCall 方法中,先利用参数构造出了一个 RealCall 对象,然后调用我们之前创建的 okHttpClient 的 eventListenerFactory 来创建一个 eventListener,传入的参数是 RealCall 对象,将创建的 eventListener 赋给 RealCall 的 eventListener 。eventListener 的作用是监听应用程序HTTP调用的数量、大小和持续时间。
  所以最终通过 okHttpClient.newCall(request) 得到的是一个 RealCall 对象。然后的步骤是调用 RealCall 对象的 execute 方法。来看一下 execute 方法。

@Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    try {
      client.dispatcher().executed(this);
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } catch (IOException e) {
      eventListener.callFailed(this, e);
      throw e;
    } finally {
      client.dispatcher().finished(this);
    }
  }

  execute方法中,最关键的代码就是。

Response result = getResponseWithInterceptorChain();

  这个方法的方法名很直接地告诉了我们,此方法通过拦截器链获取请求结果。看一下这个方法。

Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    interceptors.add(retryAndFollowUpInterceptor);
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));

    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    return chain.proceed(originalRequest);
  }

  可以从方法中看出,主要是将用户定义的 Interceptor 和 官方定义的 Interceptor 放入一个 List 中,然后创建了一个 RealInterceptorChain 拦截器链,最后调用 RealInterceptorChain 的 proceed 方法来获取请求结果。看一下 proceed 方法中做了些什么。

public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
      RealConnection connection) throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();

    calls++;

    // If we already have a stream, confirm that the incoming request will use it.
    if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
      throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
          + " must retain the same host and port");
    }

    // If we already have a stream, confirm that this is the only call to chain.proceed().
    if (this.httpCodec != null && calls > 1) {
      throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
          + " must call proceed() exactly once");
    }

    // Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);

    // Confirm that the next interceptor made its required call to chain.proceed().
    if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
      throw new IllegalStateException("network interceptor " + interceptor
          + " must call proceed() exactly once");
    }

    // Confirm that the intercepted response isn't null.
    if (response == null) {
      throw new NullPointerException("interceptor " + interceptor + " returned null");
    }

    if (response.body() == null) {
      throw new IllegalStateException(
          "interceptor " + interceptor + " returned a response with no body");
    }

    return response;
  }

  此方法中关键的代码是。

// Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);

  该方法中 index 表示的是拦截器在拦截器链中的下标,可以看到代码中有一个 index + 1 的操作,就可以知道,请求会经过拦截器的处理,一步一步传给下一个拦截器,等到最后一个拦截器获取到最初步的 response 后,又会一层一层向上传,再通过一个个拦截器的处理,得到最终的 response,整个 OkHttp 同步请求就完成了。现在关键是要知道各个拦截器做了什么工作。
  根据在拦截器中的顺序,有以下拦截器。自定义的Interceptor、RetryAndFollowUpInterceptor、BridgeInterceptor、CacheInterceptor、ConnectInterceptor、CallServerInterceptor。拦截器都要实现 Interceptor 接口。各个拦截器的功能简单介绍一下。

  • 自定义的 Interceptor,功能当然是根据需求自定义的,不过要注意的是自定义的 Interceptor 必须实现 Interceptor 接口。
  • RetryAndFollowUpInterceptor,功能是解决在请求时发生的错误并按照需求重定向。
  • BridgeInterceptor,是从应用程序代码到网络代码的桥梁。首先,它从用户请求建立网络请求,然后继续呼叫网络。最后,根据网络响应建立用户响应。
  • CacheInterceptor,缓存操作,数据有缓存就从缓存中获取,没有缓存就继续从网络上请求,将请求的结果写入缓存中。
  • ConnectInterceptor,打开目标服务器的连接并进入下一个拦截器。
  • CallServerInterceptor,链中的最后一个拦截器,它对服务器进行网络调用。

  Interceptor 是 OkHttp 最关键最核心的部分。

  再来看一下 OkHttp 异步请求部分的源码。

okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {
            @Override
            public void onFailure(okhttp3.Call call, IOException e) {

            }

            @Override
            public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {

            }
        });

  okHttpClient.newCall(request) 的步骤与同步请求相同,都是生成一个 RealCall 对象,直接看它的 enqueue 方法。

@Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

  方法中关键的代码是。

client.dispatcher().enqueue(new AsyncCall(responseCallback));

  调用了 okHttpClient 对象的 dispatcher 的 enqueue 方法,传入了回调方法的参数。看一下这个 enqueue 方法中做了什么。

synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
  }

  在此方法中,先是判断正在运行的异步操作是否大于最大的请求数以及同一个 host 是否已经到达最大的请求数,如果都满足,则将这个异步请求放入列表中并执行,否则就将它放入等待执行的队列中,需要关注的代码是。

 executorService().execute(call);

  来看一下这个 executorService() 是干什么的,看一下它的代码。

  public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }

  可以看出这个方法是用来获得一个线程池的,所以调用 execute(call) 来执行线程。看一下这个 call 是什么类型的,它应该是对我们之前的异步请求进行了包装,看一下代码。

  final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;

    AsyncCall(Callback responseCallback) {
      super("OkHttp %s", redactedUrl());
      this.responseCallback = responseCallback;
    }

    String host() {
      return originalRequest.url().host();
    }

    Request request() {
      return originalRequest;
    }

    RealCall get() {
      return RealCall.this;
    }

    @Override protected void execute() {
      boolean signalledCallback = false;
      try {
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          responseCallback.onResponse(RealCall.this, response);
        }
      } catch (IOException e) {
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }
  }

  AsyncCall 是继承自 NamedRunnable ,所以他可以被线程池执行,在它的 execute() 方法中,我们看到了熟悉的东西。

Response response = getResponseWithInterceptorChain();

  这样就可以知道了,异步请求与同步请求一样,最后也是通过拦截器链来获取请求结果。
  到这里, OkHttp 的同步请求、异步请求的流程就都理清了。接下来看一下 Retrofit 的源码。

Retrofit

  关于 Retrofit,之前有写过一篇文章 Android Retrofit2简单使用学习,可以了解一下。下面按着步骤看一下它的源码。

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

  首先需要创建一个 Retrofit 对象,对象的创建是通过 Retrofit 的内部类 Builder 来创建,这里设置了 baseUrl,还可以设置其他的参数,如果不设置则会采取默认的配置,但是 baseUrl 是不可缺少的。可以看一下 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> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

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

      // 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());
      converterFactories.addAll(this.converterFactories);

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

  可以看到,除了 baseUrl,其他的 callFactory 、converterFactories 等参数,都为我们设置了默认值,callFactory 默认是使用 OkHttpClient,最后是利用这些参数,调用了 Retrofit 的带参构造函数,返回了一个 Retrofit 对象。  下一步是创建请求的代理对象。

BookService bookService = retrofit.create(BookService.class);

  BookService 是自己编写的接口,用于写一些请求的接口,方法参数等都定义在这里。

public interface BookService {
    @GET("book/{id}")
    Call<ResponseBody> getBook(@Path("id") int id);
}

  这里需要看 Retrofit 的 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, @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);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }

  可以看出是使用了动态代理的方法。调用了 loadServiceMethod 方法获取之前定义的网络接口里的方法。看一下 loadServiceMethod 方法。

  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;
  }

  此方法返回的是 ServiceMethod 对象, 是通过 new ServiceMethod.Builder<>(this, method).build() 来获得的。我们来看一下这个方法里做了些什么。

    public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      responseConverter = createResponseConverter();

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

      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).");
        }
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      if (relativeUrl == null && !gotUrl) {
        throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError("Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError("Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError("Multipart method must contain at least one @Part.");
      }

      return new ServiceMethod<>(this);
    }

  首先是 createCallAdapter() 方法。

private CallAdapter<T, R> createCallAdapter() {
      Type returnType = method.getGenericReturnType();
      if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(
            "Method return type must not include a type variable or wildcard: %s", returnType);
      }
      if (returnType == void.class) {
        throw methodError("Service methods cannot return void.");
      }
      Annotation[] annotations = method.getAnnotations();
      try {
        //noinspection unchecked
        return (CallAdapter<T, R>) 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);
      }
    }

  这个方法里主要的工作是获取 method 的类型和注解,然后调用 retrofit.callAdapter(returnType, annotations) 方法,寻找下去,最终调用了。

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    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;
      }
    }

    StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
        .append(returnType)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
  }

  可以看出它是通过 for 循环在我们之前设置的 callAdapterFactories 里寻找适合方法的适配器,并返回,如果没有对应的就报错。
   下一步分析 build 中的 createResponseConverter 方法。

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

    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;
      }
    }

  可以看出与 createCallAdapter() 方法类似,是用来获取相应的转换器。
  loadServiceMethod 方法简单的来说,就是把之前带有注解的方法转为,配置完网络请求参数的方法。
  下一步是创建 okHttpCall 对象。

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

  创建完成之后,调用方法。

serviceMethod.adapt(okHttpCall);

  在我们之前设置好的CallAdapter中可以看到 adapt 方法。

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

  而 ExecutorCallbackCall 中的实现看一下。

  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) {
      checkNotNull(callback, "callback == null");

      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } 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);
            }
          });
        }
      });
    }

    @Override public boolean isExecuted() {
      return delegate.isExecuted();
    }

    @Override public Response<T> execute() throws IOException {
      return delegate.execute();
    }

    @Override public void cancel() {
      delegate.cancel();
    }

    @Override public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override public Call<T> clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override public Request request() {
      return delegate.request();
    }
  }

  在这个类中看到熟悉的 enqueue 和 execute ,而 delegate 就是我们之前设置的 okHttpCall 对象。看一下 OkHttpCall 这个类含有的对象。

final class OkHttpCall<T> implements Call<T> {
  private final ServiceMethod<T, ?> serviceMethod;
  private final @Nullable Object[] args;

  private volatile boolean canceled;

  @GuardedBy("this")
  private @Nullable okhttp3.Call rawCall;
  @GuardedBy("this") // Either a RuntimeException, non-fatal Error, or IOException.
  private @Nullable Throwable creationFailure;
  @GuardedBy("this")
  private boolean executed;

  可以看到有一个 okhttp3.Call 类型的对象,而所有的请求,都是由这个 okhttp3.Call 来执行。因此,下面的步骤的源码就是 OkHttp 请求的源码。

              BookService bookService = retrofit.create(BookService.class);

                Call<ResponseBody> call = bookService.getBook(1220562);

                call.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {

                        try {
                            String s = response.body().string();
                            Log.e(TAG, s);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                    }

                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                            Log.e(TAG, t.toString());
                    }
                });

  剩下的流程就是通过动态代理获得上述的对象,再进行执行,获得请求结果。
  以上就是 Retrofit 源码部分。

最后

  阅读源码可以帮助我们更好的理解框架的原理,在阅读的过程中还可以学到很多设计模式相关的知识,在日后自己的编码中可以借鉴学习。读了这两个热门框架的源码,(虽然只读了表面的流程,更深层次的代码并没有深入地去读,当然把所有实现都去读一遍是不太可能的),自己的感觉就是,造这些轮子的人太牛了,还有,读源码太累了 :)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容