OKHttp3源码分析——学习笔记

本文详细分析了OKHttp的源码,包括HttpClient与HttpUrlConnection的区别、OKHttp的架构设计,特别是Dispatcher异步请求线程池、连接池清理线程池、缓存整理线程池的工作原理。此外,还探讨了OKHttp内部缓存的使用场景、设置及源码分析,揭示了其在网络请求和缓存策略上的实现细节。
摘要由CSDN通过智能技术生成


前言 Okhttp是目前主流的网络请求框架, 我们不仅仅会用框架,而且还得知道框架的具体实现。学习完框架后写下此篇学习笔记
阅读本文前须知: 本文篇幅较长,设计内容很多,请收藏在空余时间阅读全文

1. HttpClient与HttpUrlConnection的区别

简而言之:就是Volley的的请求方式(API2.3之前用的httpClient 2.3之后用的HttpUrlconnection)

httpclient 和httpUrlConnection都支持https协议, 都是以流的形式进行传输数据.支持IPv6以及连接池等功能.

httpclient拥有很多API 保证它的兼容性进行拓展很难,google在6.0的时候废弃Httpclient AS想用这个类可以使用:org.apach.http.legacy

HttpUrlConnection:轻量级,API较少,易拓展,满足大部分的android数据传输 .例如Volley框架

2. OKHttp源码分析

  1. 使用步骤:

    首先创建OKhttpClient对象, —>再创建一个 request请求 ,给request添加url,header请求方式等参数, 用OKhttpclient.newCall方法返回一个call对象.同步方法: call.execute()来请求数据,异步:call.euque();首先创建OKhttpClient对象, 再创建一个 request请求 ,给request添加url,header请求方式等参数, 用OKhttpclient.newCall方法返回一个call对象.同步方法: call.execute()来请求数据,异步:call.euque();

     Request request = new Request.Builder().post(requestBody).url(url).build(); //得到一个request请求
        OkHttpClient okHttpClient = new OkHttpClient(); //得到OKHttpClient对象
        Call call = okHttpClient.newCall(request); //得到一个call
        call.enqueue(new Callback()); //异步
    	 // call.call.execute();//同步
     	 //  call.request().body()//得到返回体
    
  2. dispatcher任务调度器, (后面有详细说明)
    • 它定义了三个双向任务队列,二个异步队列:runningAsyncCalls和readyASyncCalls和一个运行在同步请求的runningSyncCalls队列
    • 一个标准线程池 executorServic 无界线程池,60s回收,用于大量耗时较短的异步任务
  3. Request请求
    • Request的builder方法默认请求方式为GET和请求的Url

    • 通过OKhttpclient和request构造一个call对象,它的实现时realCall

      public Call newCall(Request request) {
             
          return RealCall.newRealCall(this, request, false /* for web socket */);
      }
      
      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;
      }
      
      private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
             
          this.client = client;
          this.originalRequest = originalRequest;
          this.forWebSocket = forWebSocket;
          this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
      }
      
    • 在realCall中构造了一个RetryAndFollowUpInterceptor拦截器用于处理请求错误和重定向等,这个是Okhttp框架精髓 interceptor chain中的一环, 默认情况下的第一个拦截器,除非调用OKhttpclient.builder.addInterceptor来添加全局拦截器,在RealCall.getResponseWithInterceptorChain()中添加默认的5个拦截器

    1. RealCall
      • enque(callBack方法)

        // RealCall.java
        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));
        }
        
      • 一个call只能执行一次,否则会出现异常,这里创建一个AsyncCall并将CallBack穿入,接着交给任务分发器Dispatcher来处理

        // dispatcher.java
        synchronized void enqueue(AsyncCall call) {
                 
            //正在执行的任务数量小于最大值(64),并且此任务所属主机的正在执行任务小于最大值(5)
            if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
                 
                runningAsyncCalls.add(call);
                executorService().execute(call);
            } else {
                 
                readyAsyncCalls.add(call);
            }
        }
        
      • 从dispatcher的enqueue方法看出,对于入队做了限制,dispatcher类定义了请求数量的最大值为64个,请求的主机正再执行任务小于5台,满足以上要求的线程就可以加入队列,通过线程池执行该任务,否则加入readyAsyncCalls线程池中等待.

    2. AsyncCall
      • 它继承于NameRunnable 而NameRunnable实现runnable接口. 作用1. 采用模板方法的设计模式,让子类具体操作放在execute()中, 作用2. 给线程指定一个名称

          @Override protected void execute() {
                 
              boolean signalledCallback = false;
              try {
                 
                //调用 getResponseWithInterceptorChain()获得响应内容
                Response response = getResponseWithInterceptorChain(); //①
                if (retryAndFollowUpInterceptor.isCanceled()) {
                 
                  //这个标记为主要是避免异常时2次回调
                  signalledCallback = true;
                  //回调Callback告知失败
                  responseCallback.onFailure(RealCall.this, new IOException("Canceled")); 
                } else {
                 
                  signalledCallback = true;
                  //回调Callback,将响应内容传回去
                  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 {
                 
                //不管请求成功与否,都进行finished()操作
                client.dispatcher().finished(this);//②
              }
            }
        
      • client.dispatcher().finished(this)方法

        private void promoteCalls() {
                 
            if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
            if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
            
            //若条件允许,将readyAsyncCalls中的任务移动到runningAsyncCalls中,并交给线程池执行
            for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
                 
              AsyncCall call = i.next();
            
              if (runningCallsForHost(call) < maxRequestsPerHost) {
                 
                i.remove();
                runningAsyncCalls.add(call);
                executorService().execute(call);
              }
              //当runningAsyncCalls满了,直接退出迭代
              if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
            }
        }
        
      • promoteCalls方法推动了下个任务的执行,逻辑: 判断正在请求的队列是否大于64个,判断正在准备的队列是否为空,若条件满足, readyAsyncCall的任务移动到runningAsyncCalls中,并且交给线程池去执行

    3. interceptorChain

      • 重点就是interceptors这个集合,1. 是将前面用户自己创建的拦截器,2.添加retryAndFollowUpInterceptor错误重定向拦截器,3. 添加桥接拦截器4.缓存拦截器5.接连拦截器6.网络拦截器 最后通过RealInterceptorChain#proceed(Request)来执行interceptor chain

        Response getResponseWithInterceptorChain() throws IOException {
                 
            // Build a full stack of interceptors.
            List<Interceptor> interceptors = new ArrayList<>(); //这是一个List,是有序的
            interceptors.addAll(client.interceptors());//首先添加的是用户添加的全局拦截器
            interceptors.add
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值