OkHttp源代码分析-整体执行流程

前言

最进感触比较神的就是,学习一个框架的时候之后在阅读了源代码理解了执行流程之后,才会柔韧有余 否则就会出现每次使用的时候都需要百度或者看一下文档看看如何使用 。

整体分析

OkHttpClient

首先是OKhttp说到okhttp的整体分析,使用过okhttp的小伙伴都了解我们需要先搞一个 OkHttpClient对象 ,OKhttp支持两种构造方式

  • 默认的创建方式
 public OkHttpClient() {
    this(new Builder());
  }

可以看到这种方式,不需要配置任何参数,也就是说基本参数都是默认的,调用的是下面的构造函数

  • 使用Builder创建
//创建Builder
 OkHttpClient(Builder builder) {...}
//调用build方法创建对象
 public OkHttpClient build() {
      return new OkHttpClient(this);
 }

builder模式,通过Builder配置参数,最后通过builder()方法返回一个OkHttpClient实例。
OkHttpClient对象的创建大概就是这个样子

Request

接下来我们来聊聊Request,当你通过AndroidStudio看Request的源代码的时候你会发现 Request只提供了一种创建方式,就是通过一个Builder的建造者模式来创建。

    //获取创建Request的Builder对象
    Builder(Request request) {
      this.url = request.url;
      this.method = request.method;
      this.body = request.body;
      this.tags = request.tags.isEmpty()
          ? Collections.emptyMap()
          : new LinkedHashMap<>(request.tags);
      this.headers = request.headers.newBuilder();
    }
   // 通过Builder的build()方法创建Request对象
  public Request build() {
      if (url == null) throw new IllegalStateException("url == null");
      return new Request(this);
    }

Call
熟悉Okhttp的小伙伴也都清楚在使用okhttp的时候无论是同步的请求还是异步的请求我们都是通过Call对象来完成的,我们来看看okhttp是如何创建一个Call对象的


  /**
   * 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方法,但是这里需要注意一点,那就是方法前面的@Override注解,看到这个注解我们就要意识到,这个方法不是继承就是实现接口。

public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {...}

OkHttpClient通过实现Call.Factory这个接口向外部提供了创建Call的方式 具体的实现细节交由内部具体实现
按着流程接下来会进入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.transmitter = new Transmitter(client, call);
    return call;
  }

可以看到RealCall实现了Call接口,newRealCall这是一个静态方法,new了一个RealCall对象,并创建了一个eventListener对象

 private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    this.client = client;
    this.originalRequest = originalRequest;
    this.forWebSocket = forWebSocket;
  }

至此Call对象的创建也完成了,接下来就是发起请求了

异步请求
在创建完Call对象之后异步的请求是这样的

//请求加入调度
call.enqueue(new Callback()
        {
            @Override
            public void onFailure(Request request, IOException e)
            {
            }

            @Override
            public void onResponse(final Response response) throws IOException
            {
                    //String htmlStr =  response.body().string();
            }
        }); 

可以看到这里调用了call的enqueue方法,既然这里的call->RealCall,所以我们看一下RealCall的enqueue方法。

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

1.首先利用synchronized加入了对象锁,防止多线程同时调用,这里先判断一下executed是否为true判断当前call是否被执行了,如果为ture,则抛出异常,没有则设置为true。
2.eventListener.callStart(this);可以看到前面构建的eventListener起到作用了,这里先回调callStart方法
3.client.dispatcher().enqueue(new AsyncCall(responseCallback));这里我们就需要先回到OkHttpClient的源码中

接下来会走到Dispatcher的enqueue()-> promoteAndExecute()

 
  void enqueue(AsyncCall call) {
    synchronized (this) {
      readyAsyncCalls.add(call);

      // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
      // the same host.
      if (!call.get().forWebSocket) {
        AsyncCall existingCall = findExistingCallWithHost(call.host());
        if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
      }
    }
    promoteAndExecute();
  }
  
   private boolean promoteAndExecute() {
    assert (!Thread.holdsLock(this));

    List<AsyncCall> executableCalls = new ArrayList<>();
    boolean isRunning;
    synchronized (this) {
      for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
        AsyncCall asyncCall = i.next();

        if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
        if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.

        i.remove();
        asyncCall.callsPerHost().incrementAndGet();
        executableCalls.add(asyncCall);
        runningAsyncCalls.add(asyncCall);
      }
      isRunning = runningCallsCount() > 0;
    }

    for (int i = 0, size = executableCalls.size(); i < size; i++) {
      AsyncCall asyncCall = executableCalls.get(i);
      asyncCall.executeOn(executorService());
    }

    return isRunning;
  }

内部的逻辑就是对等待队列中的数据进行便利,当异步线程数小于最大请求数和,并且同一个请求的主机数小于maxRequestsPerHost 将请求加入到异步Running的队列中,接着便利异步Running集合 通过asyncCall.executeOn(executorService());将具体的请求传递到 AsyncCall中的execute方法()

/**
     * Attempt to enqueue this async call on {@code executorService}. This will attempt to clean up
     * if the executor has been shut down by reporting the call as failed.
     */
    void executeOn(ExecutorService executorService) {
      assert (!Thread.holdsLock(client.dispatcher()));
      boolean success = false;
      try {
        executorService.execute(this);
        success = true;
      } catch (RejectedExecutionException e) {
        InterruptedIOException ioException = new InterruptedIOException("executor rejected");
        ioException.initCause(e);
        transmitter.noMoreExchanges(ioException);
        responseCallback.onFailure(RealCall.this, ioException);
      } finally {
        if (!success) {
          client.dispatcher().finished(this); // This call is no longer running!
        }
      }
    }

 @Override protected void execute() {
      boolean signalledCallback = false;
      transmitter.timeoutEnter();
      try {
        Response response = getResponseWithInterceptorChain();
        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 {
          responseCallback.onFailure(RealCall.this, e);
        }
      } catch (Throwable t) {
        cancel();
        if (!signalledCallback) {
          IOException canceledException = new IOException("canceled due to " + t);
          canceledException.addSuppressed(t);
          responseCallback.onFailure(RealCall.this, canceledException);
        }
        throw t;
      } finally {
        client.dispatcher().finished(this);
      }
    }
  }

通过内部的getResponseWithInterceptorChain();方法来获取网络请求的数据Response

Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    interceptors.add(new RetryAndFollowUpInterceptor(client));
    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, transmitter, null, 0,
        originalRequest, this, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    boolean calledNoMoreExchanges = false;
    try {
      Response response = chain.proceed(originalRequest);
      if (transmitter.isCanceled()) {
        closeQuietly(response);
        throw new IOException("Canceled");
      }
      return response;
    } catch (IOException e) {
      calledNoMoreExchanges = true;
      throw transmitter.noMoreExchanges(e);
    } finally {
      if (!calledNoMoreExchanges) {
        transmitter.noMoreExchanges(null);
      }
    }
  }

同步请求的历程分析和异步基本相同 都是在getResponseWithInterceptorChain()中进行处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值