近期学习了网络框架Rretrofit 和其依赖的底层Okhttp.
这里做一些整理。
首先网络框架的最根本的流程
1.request —–executor ———–Httpcall |
callback- —————————————|
所以分析是基于这三个基本模块进行分析的,收先是发起一个请求,然后交给执行器,执行器执行后,返回一个回调。
根据这个思路我们开始分析Okhttp
1.request
使用时我们通过 :
//创建一个Request
final Request request = new Request.Builder()
.url("https://github.com/hongyangAndroid")
.build();
这种方式创建一个Request
2.通过:
OkHttpClient okHttpClient = new OkHttpClient();
OkHttpClient newClient = okHttpClient.newBuilder()
.cache(provideCache())
.connectTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.build();
这种方式创建一个executor
3. 通过
new Callback()
{
@Override
public void onFailure(Request request, IOException e)
{
}
@Override
public void onResponse(final Response response) throws IOException
{
//String htmlStr = response.body().string();
}
}
这些代码缠产生一个回调。
4. 通过 client.exqueue()这个方法进行异步调用
下面开始分析这些代码背后的原理。
首先上一张流程图:
Okhttp request
看源码可以知道
requeset 主要是对请求的URL header body 等信息进行的封装
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers.build();
this.body = builder.body;
this.tag = builder.tag != null ? builder.tag : this;
这里不是重点,但是这个地方在后面Retrofit 进行了注解的更高级解耦.
okhttp中executer
最重要的环节就是和executer这部分 也就是OkhttpClient
阅读源码:
我们知道这个OkhttpClient 采用的是建造者模式进行的建造,
//new call
Call call = mOkHttpClient.newCall(request);
当进行newCall这个方法之后就要执行这个Requset请求了 我们深入去看这个newCall 方法可以看到进入了一个realcall这个类,这个类就是核心类。
我们知道请求分为两种 同步和异步
通过阅读源码,同步:
Response result = getResponseWithInterceptorChain(false);
通过getResponseWithInterceptorchain 方法返回最终的Response
异步:
是通过 disapcach 这个类中的exqueue方法执行的,可以发现这个disapach 构造器生成一个线程池,并还包含3个队列。
三个队列分别为
- readyAsyncalls 等待队列
- runningAsynacalls 运行时第异步队列
- runningSyncall 运行时同步队列。
-
而最终 执行的这个对象
client.dispatcher().enqueue(new AsyncCall(responseCallback, forWebSocket));
Asyncall 实际上是一个Runnble对象 ,放入该线程池中执行的run方法还是自己的exqueue方法。 可以看到最终执行的方法仍然是
getResponseWithInterceptorChain(false);
这个方法。
殊途同归。最终都走到了这个方法中,那么这个方法则真正的获取response 和 过滤器列表的方法了。着重看这个方法。
这可以看到,其中利用了 责任链模式,环环递进,最终返回Response。
依次说以下各个拦截器的作用
1. 重定向拦截器
2. BidgeInterCepter—–Gzip 压缩 和头数据的补全,负责把用户构造的请求转换为发送到服务器的请求、把服务器返回的响应转换为用户友好的响应的 (返回代号等)。
3. CatchInterCepter—–取当初设置的缓存。catch中设置的缓存
4. connectIntercepTer –2.0 或1.0用不同的Httpstream
5. callServiceIntercepter
6. okio ————-里面用socket请求的
Okhttp中Response
真正的请求
内部是使用socket 方式请求的这里还没看到。
其中的缓存部分
而具体的缓存逻辑 OkHttp 内置封装了一个 Cache 类,它利用 DiskLruCache。按照 LRU 算法进行缓存淘汰。
如何设置缓存:
OkHttpClient okHttpClient = new OkHttpClient();
OkHttpClient newClient = okHttpClient.newBuilder()
.cache(provideCache())
.build();
设置了缓存目录。
也可以自行实现 InternalCache 接口,在构造 OkHttpClient 时进行设置,这样就可以使用我们自定义的缓存策略了。
public class CacheInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
Response response1 = response.newBuilder()
.removeHeader("Pragma")
.removeHeader("Cache-Control")
//cache for 30 days
.header("Cache-Control", "max-age=" + 3600 * 24 * 30)
.build();
return response1;
}
}
okhttp缓存设置参考文章:http://blog.youkuaiyun.com/copy_yuan/article/details/51524907
这就是Okhttp大致的请求流程。
可见Okhttp主要是在请求头 ,过滤器等方面进行的处理。
参考文章:
http://blog.piasy.com/2016/07/11/Understand-OkHttp/
http://www.open-open.com/lib/view/open1472216742720.html

960

被折叠的 条评论
为什么被折叠?



