OKHttp分发器源码分析(两个版本)
Posted 高、远
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OKHttp分发器源码分析(两个版本)相关的知识,希望对你有一定的参考价值。
文章目录
【1】简介
OkHttp
是当下android使用最频繁的网络请求框架,由Square
公司开源。 Google在Android4.4以后开始将源码中的HttpURLConnection
底层实现替换为0KHttp
,同时现在流行的Retrofit框架底层同样是使用OKHttp的。
我们将了解下OKHttp的源码,但是不同的版本源码会有一些差异,等下我会大概说一下3.10.0
和4.9.3
版本的不同之处
【2】简单使用(略谈)
大家应该都用过OKHttp,只是你们自己可能都不知道,因为我们项目中经常使用的是像Retrofit这样的网络框架,但其实Retrofit是基于OKHttp进行的再次封装,将返回的结果等进行了一些更加人性化的封装,更便于我们开发使用。
①使用流程图如下:
②使用代码如下:
//1
OkHttpClient okHttpClient = new OkHttpClient();
//2
Request request = new Request.Builder()
.url("www.baidu.com")
.build();
//3
Call call = okHttpClient.newCall(request);
//4异步请求
call.enqueue(new Callback()
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e)
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException
);
//或者同步请求
try
Response response = call.execute();
catch (IOException e)
e.printStackTrace();
其实看了这个发现OKHttp重要的还是分发器和拦截器,那么下面我们就来讲一下什么是分发器、拦截器,他们有什么用,是怎么工作的。
【3】分发器(两个版本)
Dispatcher
分发器就是来调配请求任务的,内部会包含一个线程池(异步任务才会用到)。可以在创建 OkHttpClient
时,传递我们 自己定义的线程池来创建分发器。下面我们跟着源码追一下吧,我们看异步的,同步的可以自行查看比较简单。
一、OKHttp 3.10.0版本的分发器源码追溯
①从这里进去
②Call只有一个默认实现类RealCall
③进到RealCall
的enqueue
中,发现要去到dispatcher
的enqueue
④分发器中的enqueue
分发器异步任务的时候有两个队列
runningAsyncCalls
readyAsyncCalls
running
当前任务数小于规定的max
值(默认64)(考虑到手机压力)
且running
队列里面正在访问的host和当前host相同的任务不能超过5个(减少服务器压力)
当正在执行的任务未超过最大限制64,同时 runningCallsForHost(call) < maxRequestsPerHost
同一Host的请求 不超过5个,则会添加到正在执行队列,同时提交给线程池直接执行。否则先加入等待队列。
⑤线程池执行应该是找到AsyncCall的run
方法
但他没有run
方法,而且继承的也不是Runable
对象,我们看下NamedRunnable
到底是个什么东西
⑥
原来如此,有个抽象的execute
方法在run里面执行,所以线程池就会执行AsyncCall
的execute
方法了
⑦
try和catch先不管看到finally,会执行finished
方法
⑧
将这个任务从runningAsyncCalls
中移除,然后命中if语句,进入promoteCalls
⑨
遍历readyAsyncCalls
中的任务,根据判断的规则将任务加入到runningAsyncCalls
中然后调用线程池进行执行。
现在我们想想是不是分发器我们已经走完一遍了?不是要从分发器到拦截器吗?根据我们上面的整体流程图应该是这样的,那我们什么时候进入到拦截器的呢?其实是在
execute
方法的时候:
二、OKHttp4.9.3版本的源码分析
①
②又是这个接口还是只有RealCall
这个默认实现类
③进入到RealCall
的enqueue
中
④来到dispatcher
的enqueue
方法中
这里已经是不一样的了,这里不再判断,而是直接将任务加入到readyAsyncCalls
中,然后调用promoteAndExecute
⑥
遍历,然后根据上面相同的条件,是否将任务加入到runningAsyncCalls
中,另外多了一个队列executableCalls
⑦
然后遍历执行executableCalls
队列中的任务
⑧
⑨还是要来到dispatcher
的finished
方法
这个版本的源码我没有详细讲解,但是你们应该都看得懂。跟3.10.0版本的有一些区别,但是也有很多相似的地方
三、两个不同版本的执行流程比较:
①3.10.0版本的流程
②4.9.3版本的流程
四、分发器中的线程池
这里由于篇幅,不再详细说明,这里线程池的队列用的无界队列SynchronousQueue
核心线程数为0
,最大线程数为Integer.MAX_VALUE
实现了一个最大并发量的线程池
以上是关于OKHttp分发器源码分析(两个版本)的主要内容,如果未能解决你的问题,请参考以下文章