OkHttpClient okHttpClient = new OkHttpClient.Builder().build();Request request = new Request.Builder().build();Call newCall = okHttpClient.newCall(request);//同步请求//Response response = newCall.execute();//异步请求newCall.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { }});复制代码
- 异步请求接口的Callback中的成功失败接口回调是运行在子线程
execute()总结
public Response execute() throws IOException { synchronized (this) { //判断当前call是否执行过,是的话抛异常 if (executed) throw new IllegalStateException("Already Executed"); executed = true; } captureCallStackTrace(); eventListener.callStart(this); try { //将当前call添加到Dispatcher正在执行的任务队列 client.dispatcher().executed(this); //通过一系列拦截器链做网络请求,拿到response Response result = getResponseWithInterceptorChain(); if (result == null) throw new IOException("Canceled"); return result; } catch (IOException e) { eventListener.callFailed(this, e); throw e; } finally { //从正在执行的任务队列中移除当前call client.dispatcher().finished(this); } }复制代码
- 判断当前call是否执行过,是的话抛异常
- 将当前call添加到Dispatcher正在执行的任务队列
- 通过一系列拦截器链做网络请求,拿到response
- 从正在执行的任务队列中移除当前call
异步enqueue()总结
> RealCall类enqueue()方法public void enqueue(Callback responseCallback) { synchronized (this) { //判断当前call是否执行过,是的话抛异常 if (executed) throw new IllegalStateException("Already Executed"); executed = true; } captureCallStackTrace(); eventListener.callStart(this); client.dispatcher().enqueue(new AsyncCall(responseCallback)); }复制代码
判断当前call是否执行过,是的话抛异常
将callBack封装成一个AsyncCall对象
- AsyncCall继承NamedRunnable,定义在RealCall中的内部类
- NamedRunnable是Runnable的一个实现类,Runnable的run()方法内部会调用到自己类中的一个抽象方法execute(),最终实现在AsyncCall中
> AsyncCall类execute()方法具体实现protected void execute() { boolean signalledCallback = false; try { //通过一系列拦截器链做网络请求,拿到response Response response = getResponseWithInterceptorChain(); //通过判断重定向重试拦截器是否被取消了,是的话就调用responseCallback.onFailure() 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 { //将当前请求call对象从正在运行任务队列中移除 client.dispatcher().finished(this); } }复制代码
调用client.dispatcher().enqueue()
> Dispatcher类enqueue()方法//判断正在运行异步任务队列大小是否小于最大请求数(64)并且通过runningCallsForHost()方法获取到正在运行的异步任务队列中和当前call所要请求的主机一样的调用数来判断是否小于最大请求主机数(5)//如果满足上述条件 则将当前call添加到正在运行异步任务队列中,否则添加到等待异步任务队列synchronized void enqueue(AsyncCall call) { if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) { //添加到异步任务队列 runningAsyncCalls.add(call); //开启线程池执行当前call //executorService()方法内部会判断线程池是否已经创建,是的话直接返回,否的话创建线程池 //execute() 将来某个时候执行给定的任务,任务可以在新线程或现有池中已存在的线程执行 //其实就是把AsyncCall(线程的实现类)对象放到线程池中,最后真正执行的就是AsyncCall对象的execute()方法 executorService().execute(call); } else { //添加到异步等待任务队列 readyAsyncCalls.add(call); } }复制代码
Dispatcher
什么是Dispatcher?
dispatcher的作用是维护请求的状态,并维护一个线程池,用于执行请求
Dispatcher的异步请求为什么要维护两个任务队列?
Dispatcher 生产者
ExecutorService 消费者池
- runningAsyncCalls 正在执行异步请求队列,包含没有执行完的请求但已经被取消了
- readyAsyncCalls 就绪状态异步请求队列
- executorService 执行请求的线程池
executorService()
public synchronized ExecutorService executorService() { if (executorService == null) { //corePoolSize:0 核心线程数.0的话就表示在空闲一段时间(keepAliveTime)后,会将全部线程销毁 //maximumPoolSize:Integer.MAX_VALUE 线程池允许创建最大线程数;理论上设置MAX_VALUE可以无限扩充创建线程,由于OKHttp有maxRequests(64)限制,实际并不能无限创建线程 //keepAliveTime:60 空闲线程最大存活时间.当我们的线程数大于核心线程数,多余的空闲线程最大存活时间 //3个参数含义:当线程池中任务执行完毕之后,会在60秒之后相继关闭所有空闲线程 executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new SynchronousQueue
(), Util.threadFactory("OkHttp Dispatcher", false)); } return executorService; }复制代码 移除任务call
同步请求和异步请求在拿到Response之后都会调用finished()方法
> 以下方法全是在Dispatcher类中//异步请求void finished(AsyncCall call) { finished(runningAsyncCalls, call, true);}//同步请求void finished(RealCall call) { finished(runningSyncCalls, call, false);}private
void finished(Deque calls, T call, boolean promoteCalls) { int runningCallsCount; Runnable idleCallback; synchronized (this) { //从当前任务队列中移除当前call if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!"); //调整异步请求任务队列 只有异步请求才会执行promoteCalls() if (promoteCalls) promoteCalls(); //重新计算正在执行任务数:异步请求+同步请求任务数量之和 runningCallsCount = runningCallsCount(); idleCallback = this.idleCallback; } if (runningCallsCount == 0 && idleCallback != null) { idleCallback.run(); }}/**异步请求队列重新调度.从等待队列中移除一个任务,添加到正在执行异步队列中*/private void promoteCalls() { if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity. if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote. for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) { AsyncCall call = i.next(); if (runningCallsForHost(call) < maxRequestsPerHost) { i.remove(); runningAsyncCalls.add(call); executorService().execute(call); } //如果正在执行异步队列中数量大于等于最大请求数(64),直接结束调度 if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity. }}复制代码
拦截器
拦截器是OkHttp中提供一种强大机制,它可以实现网络监听、请求以及响应重写、请求失败重试等功能
RetryAndFollowUpInterceptor
重试,失败重定向拦截器
- 创建StreamAllocation对象
- 调用RealInterceptorChain.proceed()方法进行网络请求
- 根据异常结果获取响应结果判断是否要重新请求
- 调用下一个拦截器,对Response进行处理
BridgeInterceptor
桥接适配拦截器,处理请求缺少必要的http请求头相关信息
- 负责将用户构建的一个Request请求转化为能够进行网络访问的请求
- 将这个符合网络请求的Request进行网络请求
- 将网络请求回来的响应Response转化为用户可用的Response
CacheInterceptor
缓存拦截器,通过DiskLRUCache实现缓存存取,OkHttp内部维护清理线程池,会自动清理缓存文件
ConnectInterceptor
连接拦截器,建立可用的连接
- ConnectInterceptor获取Interceptor传递过来的StreamAllocation,streamAllocation.newStream()
- 将刚才创建用于网络IO的RealConnection对象,以及对于与服务器交互最为关键的HttpCodec等对象传递后面的Interceptor
newStream()总结
- 获取到一个RealConnection
- 选择不同的链接方式
CallServerInterceptor
- 将http请求写入到网络的IO流当中,从网络io流中读取返回信息