OkHttp源码分析

一. 基本使用

https://github.com/square/okhttp
https://square.github.io/okhttp/

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

1. 三个重要对象

OkHttpClient

Call的工厂,创建一个单例,用于发送HTTP请求并读取其响应。每个clien都拥有自己的连接池和线程池,重用连接池和线程池可以减少延迟并节省内存。

OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new HttpLoggingInterceptor())
                .cache(new Cache(cacheDir, cacheSize))
                .build();

Request

HTTP请求,如果此实例的body为null或者本身是不可变的,则它们是不可变的。

Request request = new Request.Builder().url("http://www.baidu.com").build();

Call

表示已准备好执行的请求,在未完成之前可以取消请求。由于此对象表示单个请求/响应对(流),因此无法执行两次。

        Call call = client.newCall(request);
        //同步方法
        Response response = call.execute();
        //异步方法
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }

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

总结起来共三步便可发送一个请求:

  1. 创建OkHttpClient和Request对象;
  2. 将Request对象封装成Call对象;
  3. 调用Call的execute方法发送同步请求或enqueue方法发送异步请求。

2.请求步骤分析

同步请求

  1. 将请求加入到同步队列后直接执行


异步请求

  1. 将异步请求交给Dispatcher类来管理


  2. 将请求加入到准备队列,最后调用执行方法


  3. 在满足条件之后,将准备执行队列中的线程移入到执行队列中并开始执行任务。


  4. 利用线程池开始执行任务


  5. 执行线程的run方法,可以看到,在run中执行了抽象方法execute


  6. 最终执行了请求并将结果交给了回调方法。


finished方法分析

从前面的代码中可以看到,在同步请求和异步请求执行结束之后都会调用finished方法。


image.png

从代码可以很清晰的看到,finished方法中执行了两个步骤

  1. 从正在执行的任务队列中删除此任务;
  2. 在没有请求任务执行时可以执行空闲的回调。可以利用这一点,在后台执行一些耗时、优先级较低的任务。

请求流程图

注意

  1. 同步请求发送后,就会进入阻塞状态,直到收到响应。
  2. 异步请求发送后,onFailure和onResponse都是在子线程中执行的,要在这两个回调方法中执行UI操作,需要先转换到主线程。

二. Dispatcher源码分析

维护请求的状态,并维护一个线程池,用于执行请求。



Dispatcher内部维护着3个队列:

  1. readyAsyncCalls ---- 就绪等待的异步队列
  2. runningAsyncCalls --- 正在执行的异步队列
  3. runningSyncCalls --- 正在执行的同步队列
    异步调用是通过内部的线程池来消费的,最大请求个数默认是64,每个host的最大请求数是5,线程最大空闲时间60s。


    异步调用执行流程图

三. OkHttp拦截器


拦截器是OkHttp中提供的一种强大机制,它可以实现网络监听、请求以及响应重写、请求失败重试等功能,分为应用拦截器和网络拦截器两种。


OkHttp内部拦截器

拦截链执行顺序

拦截器总结:

  1. 创建一系列拦截器,并将其放入一个拦截器list中;
  2. 创建一个拦截器链RealInterceptorChain,并执行拦截器链的proceed方法,应用了责任链模式;
  3. 在发起请求前对request进行处理;
  4. 调用下一个拦截器,获取response;
  5. 对response进行处理,返回给上一个拦截器。
    利用拦截器我们可以自由的来处理request和response。比如,在实际开发上,一般有多个环境用来测试App,dev、test、release等,可以在debug环境添加一个拦截器用来替换想要请求环境的域名。

缓存

Cache put方法
  1. 只缓存Get请求
  2. 使用DiskLruCache磁盘缓存算法

连接池


连接池最大缓存空闲连接5个。内部有个线程池在每次添加连接的时候会清除空闲连接。

你可能感兴趣的:(OkHttp源码分析)