OkHttp源码解析

本文详细解读了OkHttp的源码,重点分析了DISPATCHER(分发器)的工作原理,包括同步和异步请求的执行流程。此外,还深入探讨了拦截器机制,如retryAndFollowUpInterceptor、BridgeInterceptor、CacheInterceptor、ConnectInterceptor和CallServerInterceptor的作用和工作方式。通过对OkHttp核心组件的理解,有助于提升网络请求的优化和调试能力。
摘要由CSDN通过智能技术生成

OKHTTP源码解读



一、DISPATCHER(分发器)

  1. OkHttpClient对象的创建:OKHttpClient client=new OkHttpClient.Builder().build();采用Builder设计模式创建client对象。client封装了几个重要的成员属于和方法。
    在这里插入图片描述

  2. Request对象request也是通过Builder模式生成,对象内部封装了Http请求的参数

  3. 通过调用client对象的newCall(Request request)方法返回Call对象

@Override public Call newCall(Request request) {
   
    return RealCall.newRealCall(this, request, false /* for web socket */);
}

在newCall方法内部调用了RealCall对象的静态方法返回一个Call接口的实现类RealCall对象。
4. RealCall对象主要成员属性和方法有
在这里插入图片描述
RealCall中有一个内部类AsyncCall,AsyncCall中就有一个很重要的成员变量responseCallback,就是我们网络请求的回调接口Callback,AsyncCall继承自NamedRunnable,而NamedRunnable是抽象类,并且是Runnable接口的实现类,即RealCall的内部类AsyncCall是一个线程类
5. `call.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);//通过client.dispatcher获取Dispatcher对象调用其executed()方法
      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);
    }
  }

主要执行逻辑为:
1.client.dispatcher().executed(this);//通过client.dispatcher()获取OKHttpClient的成员变量Dispatcher对象dispatcher,然后调用其executed()方法。对象dispatcher在OkHttpClient的Builder()方法中被初始化。Dispacher类的主要成员属性和方法有

在这里插入图片描述
调用dispatcher.executed(RealCall call)的执行逻辑如下,即将请求添加到运行时同步请求队列中

synchronized void executed(RealCall call) {
   
    runningSyncCalls.add(call);
}

2.Response result = getResponseWithInterceptorChain();//获取Response对象
3.client.dispatcher().finished(this);同步请求最终调用到

/** Used by {@code Call#execute} to signal completion. */
void finished(RealCall call) {
   
   finished(runningSyncCalls, call, false);
}
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
   
   int runningCallsCount;
   Runnable idleCallback;
   synchronized (this) {
   
     //请求完成 移除请求任务
     if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
     //根据传入的promoteCalls判断是否执行promoteCalls()方法,
     //同步传入的false,异步传入的true
     if (promoteCalls) promoteCalls();
     runningCallsCount = runningCallsCount();
     idleCallback = this.idleCallback;
   }

   if (runningCallsCount == 0 && idleCallback != null) {
   
     idleCallback.run();
   }
}

请求完成后调用了finished从队列中移除call请求任务

6.call.enqueue()异步请求方法的执行过程

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

首先判断运行时异步请求队列的大小小于64且每个主机的连接数小于5时将请求添加到运行时请求队列,采用线程池执行AsyncCall任务,即会执行AsyncCall的run方法中的execute()方法

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

其主要执行了
1.Response response = getResponseWithInterceptorChain();
2. client.dispatcher().finished(this);在这个方法中主要的逻辑执行为:

//异步请求最终调用
/** Used by {@code AsyncCall#run} to signal completion. */
void finished(AsyncCall call) {
   
   finished(runningAsyncCalls, call, true);
}
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
   
   int runningCallsCount;
   Runnable idleCallback;
   synchronized (this) {
   
     //请求完成 移除请求任务
     if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
     //根据传入的promoteCalls判断是否执行promoteCalls()方法,
     //同步传入的false,异步传入的true
     if (promoteCalls) promoteCalls();
     runningCallsCount = runningCallsCount();
     idleCallback = this.idleCallback;
   }
   if (runningCallsCount == 0 && idleCallback != null) {
   
     idleCallback.run();
   }
}
//异步请求的promoteCalls为true才会调用到该方法
private void promoteCalls() {
   
	//已经达到最大并发数直接return
    if (runningAsyncCalls.size() >= maxRequests) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值