OKHttp分析笔记一

1.OkHttp(OkHttp的版本implementation "com.squareup.okhttp3:okhttp:3.12.3")的常规用法,如下:

 OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("")
                .build();
        client.newCall(request)
                .enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {

                    }

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

                    }
                });

1.上面的代码中,首先从点进去enqueue()方法点进去,enqueue()方法是Call接口类中的一个抽象方法,因而继续向上寻找,点击newCall(request)方法,点进去之后,代码如下:

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

从上述代代码中我们可以知道newCall(request)方法通过RealCall.newRealCall(this,request,false)方法返回了一个实现Call接口的实例对象。我们接着往下走,点击newRealCall这个方法,代码如下:

 static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.
    //这句的大致意思是将Call的实例对象安全的发布到EventListener中
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
  }

从newRealCall()方法中参数request 是指请求报文,forWebSocket用于比较频繁的请求协议,并且服务器可以向客户端发消息,一般使用的场景股票,金融类的APP,需要秒级别的刷新频率。然后eventListener是一个监听器,他监听请求连接、请求报文等,另外由于RealCall实现了Call接口,而enqueue()方法又是接口Call里面的抽象方法,所以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)),先说client.dispacher()方法,此方法返回了一个dispatcher对象,Dispatcher是线程的的调度器,用于多线程管理,其中需要关注的两个关键变量1.maxRequest最大请求数2.maxRequestPerHost每个主机最大请求数,这两个变量可以配置配置方式setMaxRequest()和setMaxRequestsPerHost()进行配置。另外就是Dispatcher.enqueue()方法,其代码如下:

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

这个方法很简单就是将异步的call放进一个队列,然后执行promoteAndExecute()方法,我们去看一下promoteAndExecute()方法代码如下:

/**
   *Promotes eligible calls from {@link #readyAsyncCalls} to {@link #runningAsyncCalls} 
   *and runs them on the executor service. Must not be called with synchronization 
   *because executing calls can call into user code.  
   *大致意思是把符合条件的call推举出来并执行,符合条件是指没有执行过的,没有超过最大请求数
   *
   * @return true if the dispatcher is currently running calls.
   */
  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 (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.

        i.remove();
        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;
  }

这方法主要是:

第一.将符合条件的Call挑选出来放入队列;

第二将这些符合条件放入推举队列中;

第三.第三步执行这些符合条件的队列;

在第三步执行call中,调用了AsynCall中的executeOn(),而AsyncCall是RealCall的内部类,并且实现了NamedRunnable接口,

   /**
     * 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);
        eventListener.callFailed(RealCall.this, ioException);
        responseCallback.onFailure(RealCall.this, ioException);
      } finally {
        if (!success) {
          client.dispatcher().finished(this); // This call is no longer running!
        }
      }
    }

这个方法的核心在executorService.excute(this)方法,这个方法的作用是切线程,this是指在AsyncCall中的run()方法,而在Run()在AsyncCall里面没有故而去父类NamedRunnable里面找,代码如下:

@Override 
public final void run() {
    String oldName = Thread.currentThread().getName();
    Thread.currentThread().setName(name);
    try {
      execute();
    } finally {
      Thread.currentThread().setName(oldName);
    }
  }

这个方法的核心是execute()方法,而这个方法在NamedRunnable里面是抽象方法,因此从其实现的子类AysncCall中去找,其代码如下:

 @Override 
protected void execute() {
      boolean signalledCallback = false;
      timeout.enter();
      try {
        Response response = getResponseWithInterceptorChain();
        signalledCallback = true;
        responseCallback.onResponse(RealCall.this, response);
      } catch (IOException e) {
        e = timeoutExit(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);
      }
    }
  }

这个方法主要获取getResponseWithInterceptorChain(),而此时是在子线程中,而getResponseWithInterceptorChain()这个方法主要涉及OKHTTP的拦截器,这个在下面一篇文章专门讲这个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值