OKHttp源码

基本使用:

依赖:

	implementation 'com.squareup.okhttp3:okhttp:3.11.0'

使用:

	String url = "http://wwww.baidu.com";
	OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder().url(url).build();
    //Sync 同步的方式会引起线程阻塞,不允许在主线程使用
    Response response = client.newCall(request).execute();		//Catch IOException
    //Async
    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.Request.Builder—>Request—>Call(RealCall)
2.Call加入队列—>Interceptor.Chain处理—>Response

具体过程:

Reques#Builder主要成员变量:

	final HttpUrl url;
  	final String method;
  	final Headers headers;
  	final @Nullable RequestBody body;
  	final Map<Class<?>, Object> tags;

Request生成Call: Call call = client.newCall(request):

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

看看RealCall的成员变量和主要方法有什么:

final class RealCall implements Call {
	final OkHttpClient client;
	private Transmitter transmitter;
	final Request originalRequest;
	final boolean forWebSocket;
	private boolean executed;
	@Override 
 	public Call newCall(Request request) {
    	return RealCall.newRealCall(this, request, false);
 	}
 	
	@Override 
	public Response execute() throws IOException {
    	synchronized (this) {
      		if (executed) throw new IllegalStateException("Already Executed");
     	 	executed = true;
    	}
    	transmitter.timeoutEnter();
    	transmitter.callStart();
    	try {
    		//同步处理请求将realCall加入一个队列,this = Realcall
      		client.dispatcher().executed(this);		
      		//在当前线程调用来拦截器链处理请求
      		return getResponseWithInterceptorChain(); 	
    	} finally {
      		client.dispatcher().finished(this);		//this = Realcall,Realcall出队
    	}
 	}
 	
	@Override 
	public void enqueue(Callback responseCallback) {
    	synchronized (this) {
      		if (executed) throw new IllegalStateException("Already Executed");
     	 	executed = true;
    	}
    	transmitter.callStart();
    	//异步处理请求将一个AsyncCall加入队列
    	client.dispatcher().enqueue(new AsyncCall(responseCallback));
	}
	
	@Override 
	public void cancel();
	
	Response getResponseWithInterceptorChain()
	
	//RealCall内部类AsynCall专门用来处理异步请求,封装了realCall和回调接口,使执行过程切换到其他线程
	final class AsyncCall extends NamedRunnable {		//间接实现了Runnable接口
		 private final Callback responseCallback;
		 void executeOn(ExecutorService executorService);
		 @Override
		 public final void run() {			
      		execute();
      	 }
      	 
    	 @Override
    	 protected void execute() {			//与RealCall基本相同的逻辑,都是用责任链处理Call返回Response
      		try {
      			//调用来拦截器链处理请求
        		Response response = getResponseWithInterceptorChain();
        		responseCallback.onResponse(RealCall.this, response);
      		} catch (IOException e) {
          		responseCallback.onFailure(RealCall.this, e);
      		} finally {
        		client.dispatcher().finished(this);		//AsynCall出队
      		}
    	}
	}

}

可见同步处理请求和异步处理请求的流程大致都相同,都是先把请求加入队列,然后调用getResponseWithInterceptorChain方法用拦截器链处理,下面分开来看两个过程:

将同步或异步的请求加入Dispatcher中的任务队列:

public final class Dispatcher {
	private int maxRequests = 64; 												//最大请求数量
    private int maxRequestsPerHost = 5; 										//每台主机最大的请求数量
    
	private @Nullable ExecutorService executorService; 							//一个线程池
	private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>(); 		//异步准备队列
	private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>(); 		//异步正在执行队列
	private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>(); 		//同步正在执行队列
	
	//获取一个线程池,这个线程池没有核心线程,线程数量没有限制,空闲60s就会回收*/
	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;
    }



	synchronized void executed(RealCall call) {				//分发器执行就是把Realcall加入同步正在执行队列中去
    	runningSyncCalls.add(call);
  	}
  	
  	void enqueue(AsyncCall call) {
    	synchronized (this) {
      	readyAsyncCalls.add(call);		//先加入异步准备队列中
     	if (!call.get().forWebSocket) {
       		AsyncCall existingCall = findExistingCallWithHost(call.host());
        	if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
      		}
    	}
    	promoteAndExecute();	
  	}
	private boolean promoteAndExecute() {											//省略部分逻辑
    	List<AsyncCall> executableCalls = new ArrayList<>();
    	boolean isRunning;
      	for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {	//遍历异步准备队列
        	if (runningAsyncCalls.size() >= maxRequests) break; 			//正在处理的请求数达到最大,跳出循环
        	executableCalls.add(asyncCall);									//否则加入正在执行队列
        	runningAsyncCalls.add(asyncCall);
      	}
      	for (int i = 0, size = executableCalls.size(); i < size; i++) {				//遍历可执行Asyncall队列
      		AsyncCall asyncCall = executableCalls.get(i);
      		//依次将这些Asyncall交给线程池处理(AsnyCall实现了Runnable接口)
      		asyncCall.executeOn(executorService());		
    	}
      	isRunning = runningCallsCount() > 0;
      	return isRunning;
    }
}

可以看到Dispatcher的功能非常简单,就是维护三个队列,规划异步请求的执行顺序

接下来看创建拦截器链处理请求的方法:

 //ClassName = RealCall
 Response getResponseWithInterceptorChain() throws IOException {
    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));
    
    //用List<Interceptor>可以构造一个对象
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null, 0,
        originalRequest, this, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());
        
    //用RealInterceptorChain处理实际请求
    return chain.proceed(originalRequest);
}

OkHttpClient可以通过两种方式添加拦截器:·

	OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(xxx)
            .addNetworkInterceptor(xxx)

由源码可知,各个拦截器的执行顺序为:
自定义普通拦截器,retry,bridge,cache,connect,自定义网络拦截器,callServer拦截器

拦截器链调用过程:

//ClassName = RealInterceptorChain
public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
	throws IOException {		//省略部分逻辑
	//index表示当前拦截器在连接器链中的index,拦截器链处理请求前要先用后面的拦截器构建一条新的拦截器链;
 	RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
        index + 1, request, call, connectTimeout, readTimeout, writeTimeout);	
    //获取当前拦截器;
    Interceptor interceptor = interceptors.get(index);
    //用当前拦截器处理请求(请求包含在拦截器链next.request中),next为后续所有拦截器组成的链
    Response response = interceptor.intercept(next);
}

拦截器的intercept方法使用的参数是chain,这样设计的目的是,将是否调用后续的拦截器的控制权交给拦截器本身;如果无需后续拦截器处理,由当前拦截器生成Response返回,如果需要后续拦截器处理,则由当前拦截器调用chain.proceed()

5个默认拦截器:

看拦截器代码首先要找到 realChain.proceed(…),这句代码会调用后续拦截器处理,把Request转化为Response,这句代码之前的逻辑都用来处理Request,之后的代码都用来处理Response。

重定向拦截器:

public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Call call = realChain.call();
    EventListener eventListener = realChain.eventListener();
	//这里新建了一个流对象,负责数据传输
    StreamAllocation streamAllocation = new StreamAllocation(client.connectionPool(),
        createAddress(request.url()), call, eventListener, callStackTrace);
    this.streamAllocation = streamAllocation;

    int followUpCount = 0;
    Response priorResponse = null;
    while (true) {
      if (canceled) {
        streamAllocation.release();
        throw new IOException("Canceled");
      }

      Response response;
      boolean releaseConnection = true;


      try {
      	//这里调用后续拦截器处理request,是request和respone的分界线
        response = realChain.proceed(request, streamAllocation, null, null);		
        releaseConnection = false;
      } catch (Exception e) {
      	//...
        releaseConnection = false;
        continue;
      } finally {
        // 走到这里说明请求成功了,释放资源
        if (releaseConnection) {
          streamAllocation.streamFailed(null);
          streamAllocation.release();
        }
      }
	  ...
      Request followUp;
      try {
      	//follow就是重定向之后产生的新的request;若要获取正确的相应,需要重新进行一次请求
        followUp = followUpRequest(response, streamAllocation.route());
      } catch (IOException e) {
        streamAllocation.release();
        throw e;
      }
	  //重定向请求为空,说明请求已完成,不需要重定向,释放资源
      if (followUp == null) {
        streamAllocation.release();
        return response;
      }

      closeQuietly(response.body());

	  //重定向太多次了,抛出异常,释放资源
      if (++followUpCount > MAX_FOLLOW_UPS) {
        streamAllocation.release();
        throw new ProtocolException("Too many follow-up requests: " + followUpCount);
      }
	  
      if (followUp.body() instanceof UnrepeatableRequestBody) {
        streamAllocation.release();
        throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
      }

      if (!sameConnection(response, followUp.url())) {
        streamAllocation.release();
        streamAllocation = new StreamAllocation(client.connectionPool(),
            createAddress(followUp.url()), call, eventListener, callStackTrace);
        this.streamAllocation = streamAllocation;
      } else if (streamAllocation.codec() != null) {
        throw new IllegalStateException("Closing the body of " + response
            + " didn't close its backing stream. Bad interceptor?");
      }
      //走到这里,由于重定向或请求失败,需要重新请求
	  //这里用follow替换了request,做while循环
      request = followUp;
      priorResponse = response;
    }
}

BridgeInterceptor: 主要负责添加Http头部,和处理gzip等

public Response intercept(Chain chain) throws IOException {
	Request userRequest = chain.request();
	
	...
	//为Request添加Head
	if (userRequest.header("Connection") == null) {
    	  requestBuilder.header("Connection", "Keep-Alive");
    }
	if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
        transparentGzip = true;
        requestBuilder.header("Accept-Encoding", "gzip");
    }
	...
	
	
  	Response networkResponse = chain.proceed(requestBuilder.build());


	//接收返回的cookie
	HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());
	//处理gzip
	if (transparentGzip
        	&& "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
        	&& HttpHeaders.hasBody(networkResponse)) {
      	GzipSource responseBody = new GzipSource(networkResponse.body().source());
     	 Headers strippedHeaders = networkResponse.headers().newBuilder()
          	.removeAll("Content-Encoding")
          	.removeAll("Content-Length")
          	.build();
      	responseBuilder.headers(strippedHeaders);
      	String contentType = networkResponse.header("Content-Type");
      	responseBuilder.body(new RealResponseBody(contentType, -1L, Okio.buffer(responseBody)));
   }

    return responseBuilder.build();
}

缓存拦截器:

//ClassName = CacheInterceptor
@Override
public Response intercept(Chain chain) throws IOException {
	//cache不为空的话直接从缓存中获取Response
    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;	//== null if 网络不可用或不需要
    Response cacheResponse = strategy.cacheResponse;	//== null if 缓存为空

    if (cache != null) {
      cache.trackResponse(strategy);
    }

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

    // 如果网络不可用,且缓存不可用,本地构造一个失败的响应并返回;
    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 (networkRequest == null) {
      return cacheResponse.newBuilder()
          .cacheResponse(stripBody(cacheResponse))
          .build();
    }
	// 以下逻辑都基于需要网络且网络可用!!!
    Response networkResponse = null;



    networkResponse = chain.proceed(networkRequest);



	// 此时获取了网络调用产生的响应
    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();

        cache.trackConditionalCacheHit();
        //更新缓存并返回响应结果
        cache.update(cacheResponse, response);
        return response;
      } else {
        closeQuietly(cacheResponse.body());
      }
    }

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

1.发送请求前:
网络缓存都不可用,返回一个失败的响应;
网络不可用,缓存可用,从缓存获取;
网络可用,缓存不可用,调用后续的拦截器处理请求;

2.得到远端数据之后:
检查缓存开关是否开启,可用则更新缓存结果

连接池拦截器:
ConnectInterceptor主要是从连接池去取连接,http请求要先3次握手才能建立连接,复用连接可以免去握手的时间。

public Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Request request = realChain.request();
    StreamAllocation streamAllocation = realChain.streamAllocation();

    // We need the network to satisfy this request. Possibly for validating a conditional GET.
    boolean doExtensiveHealthChecks = !request.method().equals("GET");
    // 获取HttpCodec,会从连接池获取连接
    HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
    RealConnection connection = streamAllocation.connection();

    return realChain.proceed(request, streamAllocation, httpCodec, connection);
  }
  
  //
  public HttpCodec newStream(
     ...
    try {
    //顾名思义,就是找一个连接
      RealConnection resultConnection = findHealthyConnection(connectTimeout, readTimeout,
          writeTimeout, pingIntervalMillis, connectionRetryEnabled, doExtensiveHealthChecks);
      HttpCodec resultCodec = resultConnection.newCodec(client, chain, this);

      synchronized (connectionPool) {
        codec = resultCodec;
        return resultCodec;
      }
    } catch (IOException e) {
      throw new RouteException(e);
    }
  }
  
   //获取连接的方法
   private RealConnection findHealthyConnection(int connectTimeout, int readTimeout,
      int writeTimeout, int pingIntervalMillis, boolean connectionRetryEnabled,
      boolean doExtensiveHealthChecks) throws IOException {
    while (true) {
      RealConnection candidate = findConnection(connectTimeout, readTimeout, writeTimeout,
          pingIntervalMillis, connectionRetryEnabled);

      // If this is a brand new connection, we can skip the extensive health checks.
      synchronized (connectionPool) {
        if (candidate.successCount == 0) {
          return candidate;
        }
      }
      
      if (!candidate.isHealthy(doExtensiveHealthChecks)) {
        noNewStreams();
        continue;
      }

      return candidate;
    }
  }

CallServerInterceptor:最后一个拦截器,它向服务器发起真正的网络请求

public Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    HttpCodec httpCodec = realChain.httpStream();
    StreamAllocation streamAllocation = realChain.streamAllocation();
    RealConnection connection = (RealConnection) realChain.connection();
    Request request = realChain.request();

    long sentRequestMillis = System.currentTimeMillis();

    realChain.eventListener().requestHeadersStart(realChain.call());
    httpCodec.writeRequestHeaders(request);
    realChain.eventListener().requestHeadersEnd(realChain.call(), request);

    Response.Builder responseBuilder = null;
	//...
    Response response = responseBuilder
        .request(request)
        .handshake(streamAllocation.connection().handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(System.currentTimeMillis())		//获取response
        .build();
    code = response.code();
	if(code  == 100) {
		//重试一次
		responseBuilder = httpCodec.readResponseHeaders(false);
        response = responseBuilder
              .request(request)
              .handshake(streamAllocation.connection().handshake())
              .sentRequestAtMillis(sentRequestMillis)
              .receivedResponseAtMillis(System.currentTimeMillis())
              .build();
        code = response.code();
	}
	if(code  == 101){
		...
	}
	if(code  == 204 || code == 205){
		throw new ProtocolException(xxxx);
	}
    return response;
 }

https://blog.csdn.net/asffghfgfghfg1556/article/details/80787240

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值