Android框架源码解析之(二)OKhttp

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29375837/article/details/81512058

源码在:https://github.com/square/okhttp
包实在是太多了,OKhttp核心在这块https://github.com/square/okhttp/tree/master/okhttp
直接导入Android Studio中即可。

基本使用:

//1、创建OkHttpClient 

OkHttpClient mOkHttpClient = new OkHttpClient();


//2、创建Request
        final Request request = new Request.Builder()
                .url("https://www.jianshu.com/u/b4e69e85aef6")
                .addHeader("user_agent","22222")
                .build();

//3、创建Call
          Call call = mOkHttpClient.newCall(request);
//4、执行call.enqueue
          call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if(response != null )
                Log.i(TAG, "返回服务端数据:"+ String.valueOf(response.body().string()));
            }
        });

源码解析:

1、创建OkHttpClient



//OkHttpClient.java


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

  OkHttpClient(Builder builder) {
    //调度器
    this.dispatcher = builder.dispatcher;
    this.proxy = builder.proxy;
    //默认支持的Http协议版本  --   Protocol.HTTP_2, Protocol.HTTP_1_1;
    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);
    }
  }

通过建造者模式为我们设置默认的OKhttpClient

2、创建Request



//Request.java

  Request(Builder builder) {
    //请求的url
    this.url = builder.url;
    //请求的方式
    this.method = builder.method;
    //请求头
    this.headers = builder.headers.build();
    //请求体
    this.body = builder.body;
    this.tags = Util.immutableMap(builder.tags);
  }


//具体的设置我就不贴了,可以看出通过建造者模式创建Request

public Builder newBuilder() {
    return new Builder(this);
  }

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

通过建造者模式创建Request

3、创建Call

     Call call = mOkHttpClient.newCall(request);

源码:

  @Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web 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;
  }

实际上是创建了RealCall对象

4、执行RealCall.enqueue方法,异步请求


  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      //为保证线程安全,若已经执行,抛出IllegalStateException
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);

//重点在这里
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

可以看出最终的请求是dispatcher来完成的

看一下同步请求代码:

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

在这里可以看出
异步请求调用了dispatcher().enqueue
同步请求调用了dispatcher().executed

接下来分析dispatcher

5、Dispatcher
Dispatcher主要用于控制并发的请求,主要维护了以下变量

//最大并发请求数
  private int maxRequests = 64;
  //每个主机的最大请求数
  private int maxRequestsPerHost = 5;
  private @Nullable Runnable idleCallback;

  /** Executes calls. Created lazily. */
  //消费者线程池
  private @Nullable ExecutorService executorService;

  /** Ready async calls in the order they'll be run. */
  //将要运行的异步请求队列
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();

  /** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
  //正在运行的异步请求队列
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();

  /** Running synchronous calls. Includes canceled calls that haven't finished yet. */
  //正在运行的同步请求队列
  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();

接下来看看Dispatche的构造方法

  public Dispatcher(ExecutorService executorService) {
    this.executorService = executorService;
  }

  public Dispatcher() {
  }

  public synchronized ExecutorService executorService() {
    if (executorService == null) {
    //如果用户没有设置自己的线程池,自OKhttp初始化默认的线程池
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }

Dispatcher有两个构造方法,可以使用自己的线程池。如果没有设置自己的线程池,则会设置默认的线程池。这个线程池类类似于CachedThreadPool,比较适合执行大量的耗时比较少的任务。

接下来看看Dispatcher的同步执行方法

  /** Used by {@code Call#execute} to signal it is in-flight. */
  synchronized void executed(RealCall call) {
    //将请求添加到同步运行队列
    runningSyncCalls.add(call);
  }

Dispatcher的异步执行方法


  synchronized void enqueue(AsyncCall call) {

    /*当正在运行的异步请求队列中的数量小于64并且正在运行的请求主机数小于5时
    把请求添加到runningAsyncCalls
    否则,将请求添加到readyAsyncCalls
     */

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

接下来调用executorService().execute(call);,实际调用的是AsyncCall的execute方法,接下来分析

6、AsyncCal的execute方法

AsyncCall是RealCall的内部类,其内部也实现了execute方法,如下:

 @Override protected void execute() {
      boolean signalledCallback = false;
      try {

        //在这块实现了网络请求,并返回Response
        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);
      }
    }
  }

可以看出,网络请求操作在Response response = getResponseWithInterceptorChain();中执行
下面分析getResponseWithInterceptorChain()

7、RealCall.getResponseWithInterceptorChain()

  Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.

    //添加各种Interceptor


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

可以看出创建了RealInterceptorChain它是一个拦截器链,这个类也是RealCall的内部类,接下来执行它的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;
  }

拦截器的作用

来自官网的英文原文:

Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls.

意思大概是,拦截器是一个强有力的机制,,它可以实现网络监听、请求以及响应重写、请求失败重试等功能。

这里写图片描述

这里不做过多分析,具体详情可以看看这篇文章
https://blog.csdn.net/lepaitianshi/article/details/72457928

具体的网络请求已经在拦截器中实现

* CacheInterceptor实现缓存管理*

@Override public Response intercept(Chain chain) throws IOException {
    Response cacheCandidate = cache != null
        ? cache.get(chain.request())
        : null;

    long now = System.currentTimeMillis();

    CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();

    //网络请求
    Request networkRequest = strategy.networkRequest;
    //缓存响应
    Response cacheResponse = strategy.cacheResponse;

    if (cache != null) {
      //记录当前请求是网络发起还是缓存发起
      cache.trackResponse(strategy);
    }

    if (cacheCandidate != null && cacheResponse == null) {
      closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it.
    }

    // If we're forbidden from using the network and the cache is insufficient, fail.
    //不进行网络请求,并且缓存不存在,则返回504错误
    if (networkRequest == null && cacheResponse == null) {
      return new Response.Builder()
          .request(chain.request())
          .protocol(Protocol.HTTP_1_1)
          .code(504)
          .message("Unsatisfiable Request (only-if-cached)")
          .body(Util.EMPTY_RESPONSE)
          .sentRequestAtMillis(-1L)
          .receivedResponseAtMillis(System.currentTimeMillis())
          .build();
    }

    // If we don't need the network, we're done.
    //如果不进行网络请求,而且缓存可用,则直接返回缓存
    if (networkRequest == null) {
      return cacheResponse.newBuilder()
          .cacheResponse(stripBody(cacheResponse))
          .build();
    }


    //请求网络
    Response networkResponse = null;
    try {
      networkResponse = chain.proceed(networkRequest);
    } finally {
      // If we're crashing on I/O or otherwise, don't leak the cache body.
      if (networkResponse == null && cacheCandidate != null) {
        closeQuietly(cacheCandidate.body());
      }
    }

    // If we have a cache response too, then we're doing a conditional get.
    //如果存在缓存,并且服务器没有修改数据(networkResponse.code() == HTTP_NOT_MODIFIED),则返回缓存
    if (cacheResponse != null) {
      if (networkResponse.code() == HTTP_NOT_MODIFIED) {
        Response response = cacheResponse.newBuilder()
            .headers(combine(cacheResponse.headers(), networkResponse.headers()))
            .sentRequestAtMillis(networkResponse.sentRequestAtMillis())
            .receivedResponseAtMillis(networkResponse.receivedResponseAtMillis())
            .cacheResponse(stripBody(cacheResponse))
            .networkResponse(stripBody(networkResponse))
            .build();
        networkResponse.body().close();

        // Update the cache after combining headers but before stripping the
        // Content-Encoding header (as performed by initContentStream()).
        cache.trackConditionalCacheHit();
        cache.update(cacheResponse, response);
        return response;
      } else {
        closeQuietly(cacheResponse.body());
      }
    }


    //f否则进行网络请求
    Response response = networkResponse.newBuilder()
        .cacheResponse(stripBody(cacheResponse))
        .networkResponse(stripBody(networkResponse))
        .build();

    if (cache != null) {
      if (HttpHeaders.hasBody(response) && CacheStrategy.isCacheable(response, networkRequest)) {
        // Offer this request to the cache.
        CacheRequest cacheRequest = cache.put(response);
        return cacheWritingResponse(cacheRequest, response);
      }

      if (HttpMethod.invalidatesCache(networkRequest.method())) {
        try {
          cache.remove(networkRequest);
        } catch (IOException ignored) {
          // The cache cannot be written.
        }
      }
    }

    return response;
  }

如果缓存存在而且没有过期(服务器返回数据为304),则返回响应,否则请求网络

这里的缓存均基于Map,key是请求中url的md5,value是文件中查询到的缓存,页面置换基于LRU算法。

这里写图片描述

至此源码就分析到这,主要是拦截器链起作用,具体的话,可以看看这篇文章
https://blog.csdn.net/lepaitianshi/article/details/72457928

猜你喜欢

转载自blog.csdn.net/qq_29375837/article/details/81512058