OkHttp源码分析

本文详细分析了OkHttp 3.4.1版本的源码,重点讲解了Dispatcher的调度逻辑、Request的执行流程以及线程池的使用。通过拦截器链的执行顺序,揭示了OkHttp如何进行请求管理、缓存处理、连接复用等核心功能。在无网络的情况下,OkHttp能够利用缓存提供接口数据。此外,还讨论了如何通过调试跟踪拦截器的执行过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        用了一段时间的OkHttp库,版本3.4.1。  最近总算有时间看看源码了, 主要是根2.4.0版本的区别;

         看了篇讲OkHttp的博客http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0326/2643.html , 3.4.1版本有很大变化,  没有HttpClient了。

         对于互联网app在使用okhttp时, 一般都是实例化一个Request后交给OkHttpClient。 OkHttpClient通过Dispatcher类(做调度逻辑的, 可以理解为司令的作用)从队列(针对异步方式)里取出请求(Call是一次请求/返回的执行单元),从内存或服务器取数据,并加入到执行队列runningAsyncCalls里, 如果超过限制(做多并发64个请求或相同host的5个请求)则加入到待执行队列readyAsyncCalls; 对于同步方式则执行,并放到runningSyncCalls中管理;

         从上图也可以看出OkHttp支持缓存, 即无网络请求下也能拿到接口数据(从上次成功的文件缓存里);OkHttp也使用了线程池, 对使用OkHttp的app来说就不要再创建线程或线程池使用OkHttp了。 多线程并发下载/上传文件的实现方法可以我的上篇博客。



          我只画了一部分类图, 要了解OkHttp的调度必须要看Dispather.java, 这个类就是OkHttp的大管家, 它是管着干活的Call类。 Dispatcher.java里有个成员变量executeService, 所有异步请求都是在这个线程池里执行的, 在下面的时序图里Dispatcher之前的时序是同步执行的, Dispatcher后的流程都是在子线程执行的。

         ConnectionPool.java也有个线程池变量executor, 从类名看出它是用来复用tcp连接的, 有点像长连接, 在文章头那篇引用博客里讲到了。

          在OkHttp框架里用到线程池的就是Dispatcher和ConnectionPool类。

        


         上图是异步请求的时序图, 其中最关键的函数是RealCall类里的getResponseWithInterceptorChain, 默认有5个interceptor对象。

      private Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());     //app设置的自定义拦截器,比如说每个接口要判断是否已登录
    interceptors.add(retryAndFollowUpInterceptor);   //第1个
    interceptors.add(new BridgeInterceptor(client.cookieJar())); //第2个
    interceptors.add(new CacheInterceptor(client.internalCache()));   //缓存拦截器,第3个
    interceptors.add(new ConnectInterceptor(client)); //连接池, 复用连接。第4个
    if (!retryAndFollowUpInterceptor.isForWebSocket()) {
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(
        retryAndFollowUpInterceptor.isForWebSocket()));  //第5个


    Interceptor.Chain chain = new RealInterceptorChain(
        interceptors, null, null, null, 0, originalRequest);
    return chain.proceed(originalRequest);
  }

        可以看出每个请求最终都执行到接口Interceptor的实现类中, 为了看明白chain.proceed(originalRequest)的执行过程, 我注释了interceptors.add(new CallServerInterceptor( retryAndFollowUpInterceptor.isForWebSocket()));这行代码,  然后执行会崩溃并打印堆栈, 这样就能看到这4/5个拦截器的执行时序了。

                                                                              java.lang.AssertionError
                                                                                  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:72)
                                                                                  at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
                                                                                  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
                                                                                  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
                                                                                  at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:109)
                                                                                  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
                                                                                  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
                                                                                  at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
                                                                                  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
                                                                                  at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
                                                                                  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
                                                                                  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
                                                                                  at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:186)
                                                                                  at okhttp3.RealCall.access$100(RealCall.java:35)
                                                                                  at okhttp3.RealCall$AsyncCall.execute(RealCall.java:134)
                                                                                  at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
                                                                                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                                                                                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                                                                                  at java.lang.Thread.run(Thread.java:818

          从上面堆栈看出OkHttp是使用拦截器做各种逻辑的,  通过实现接口类Interceptor的intercept函数来做各种功能;

public interface Interceptor {
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;

    Connection connection();
  }
}


    下图是调试步骤截图:















      我的微信公众号, 欢迎关注, 让我们一起成长大笑

                         


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值