美文网首页Android技术知识Android开发Android开发
OkHttp源码 和 Retrofit源码 一起读

OkHttp源码 和 Retrofit源码 一起读

作者: reggie1996 | 来源:发表于2018-08-26 21:10 被阅读114次

      平时有在用 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 源码部分。

    最后

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

    相关文章

      网友评论

        本文标题:OkHttp源码 和 Retrofit源码 一起读

        本文链接:https://www.haomeiwen.com/subject/azhbiftx.html