okhttp网络框架
- OkHttp使用简介
- OkHttp源码剖析
1.OkHttp使用简介
图图
图
图
- 创建客户端
OkhttpClient client = new OkHttpClient();//作为单例,这样所有的请求可以公共response缓存和线程池
- 创建客户端
- 创建Request对象
Request request = new Request.Builder().url("http://xxx").build();
图上:封装了Http的一些请求信息
Builder模式构建,builder模式会将它的显示和创建所分离
- 创建Request对象
- 创建Call对象,call对象就是一个Http请求,execute开始执行
okttp3.Response response = client.newCall(request).execute();
//其中Call是连接request和Response的的桥梁
Call对象既可以同步获取时间,也可以异步获取获取
- 创建Call对象,call对象就是一个Http请求,execute开始执行
//同步获取方法
if(!response.isSuccessful())
throw new IOException("Unexpected code "+response);
Headers responseHeaders = response.headers()
for(int i=0;i<responseHeaders.size();i++){
System.out.println(responseHeaders.name(i)+": "+responseHeaders.value(i));
}
System.out.println(response.body().string());
同步获取数据它会阻塞当前线程去请求数据,返回response对象给线程.response也会包含状态码,响应头,响应body
//异步获取方法:
//前两步一样:
client.newCall(request).enqueue(new Callback(){
public void onFailure(Call call,IOException e){
e.printStackTrace();
}
public void onResponse(Call call,okhttp3.Response response) throws IOExcepiton{
if(!response.isSuccessful())
throw new IOException("Unexpected code "+response);
Headers responseHeaders = response.headers();
for(int i=0;i<responseHeaders.size();i++){
System.out.println(responseHeaders.name(i)+": "+responseHeaders.value(i));
}
System.out.println(response.body().string());
}
})
enqueue方法不会阻塞当前进程,会开启子线程,网络请求在子线程操作,当请求结束后,会回调成功、失败(在工作线程中执行)
2.OkHttp源码剖析
图:
图
7-1 okhttp网络框架面[00_06_58][20180721-155323-5].jpg 图 图 图 图
1. Application
2.Application INTERCEPTORS 包括↓request ↑response
OkHttp core
1.↓CACHE ↑CACHE 2.NETWORK INTERCEPTORS ↓request ↑response
- 创建客户端
OkhttpClient client = new OkHttpClient();
- 创建客户端
- 2.创建Request对象
Request request = new Request.Builder().url("http://xxx").build();
//builder模式的作用就是将一个复杂对象的构建与他的表示像分离,这样就可以是同样的构建过程创建不同的的表示 - 3.okttp3.Response response = client.newCall(request).execute();
- newCall()里面是 return new RealCall(this.request,false);
RealCall类中方法;
public Response execute()throw IOException {
synchronized(this){
//检查
if(executed) throw new IllegalStateException("Already Executed")
executed = true;
}
//每个call只能执行一次,如果想要一个完全的方法,可以使用call.clone方法
captureCallStackTrace();
try{
client.dispatcher().executed(this);//开始同步请求
//dispatcher官方文档中它是一个异步请求的策略,但是它也能做一些同步请求的操作
Response result = getResponseWithInterceptorChain();
//okhttp最精髓的地方,拦截器。经过拦截器拦截后,会返回一个response结果给我们的http
if(result = null) throw new IOException("Canceled");
return result;
}finally{
client.dispathcher().finished(this);
//通知我们的dispatcher 任务完成
}
}
//以下finished的源码
finished(runningSyncCalls,call,false);
即
private <T> void finished(Deque<T> calls,T call,boolean promoteCalls){
int runningCallsCount;
Runnable idleCallback;
synchronized(this){
if(!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
if(promoteCalls) promoteCalls();
runningCallsCount = runningCallsCount();
idleCallback = this.idleCallback;
}
if(runningCallsCount == 0 && idleCallback !=null){
idleCallback.run();
}
}
//做的工作:把请求队列关闭
在同步操作中,client.dispatcher().executed(this)中涉及到dispatcher并不是真正的去做异步操作,只是告诉我们执行的状态。开始执行时executed,执行完了finished方法
真正做网络请求并返回结果的是方法getResponseWithInterceptorChain();
Response getResponseWithInterceptorChain() throw IOExption{
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors);
interceptors.add(retryAndrFollowUpInterceptor);
interceptors.add(new BirdgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if(!forWebSocket){
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
Intercepor.Chain chain = new RealInterceptorChain(interceptors,null,null,null,0,originalRequest);
return chain.proceed(originalRequest);
}
interceptor 它把网络请求缓存,压缩等所有功能都统一起来,每一个都是interceptor,连接起来成了一个interceptor.chain
-
各拦截器
retryAndrFollowUpInterceptor -->失败重试,重定向,重定向另外一个url
BirdgeInterceptor 为了把用户构造的请求转换成发送到服务器的请求,然后把服务器的响应转回给用户,进行一些友好输出的响应,这是一个桥接的interceptor
CacheInterceptor :缓存拦截器,读取,更新缓存
ConnectInterceptor :和服务端进行连接的拦截器
CallServerInterceptor :网络的服务器端的连接
具体分析一个拦截器:
CallServerInterceptor
类结构
+boolean forWebSocket:构造赋值
--------------------
public Response intercept(Chain chain) throws IOExcetion{
}
- 主要作用,向服务器发送一个头部,如果有body也会发送。发送之后获取response的头部和body
- 其中httpCodec.writeRequestHeaders(request),需要关注httpCodec它的内部是Okio对象 ,okio封装了socket;
- interceptor设计是一个分层的思想,每一个interceptor就是一层,这是tcp/ip协议是异曲同工之秒、
- 每一层简化了,每一层只关心每一层的事情,比如CallServerInterceptor只关心和服务器的连接;
把各种复杂的任务拆分成一个一个独立的任务,这样对以后的拓展很有帮助。
异步请求源码分析
enqueue也是在RealCall里面处理的
public void enqueue(Callback responseCallback){
//同上检查是否已执行
captureCallStackTrace();
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
Dispatcher 的enqueue方法:
synchronized void enqueue(AsyncCall call){
if(runningAsyncCalls.size()<maxREquests && runningCallsForHost(call) < maxRequestsPerHost){
runningAsyncCalls.add(call);//满足要求添加到队列里面
executorService().execute(call);
}else{
readyAsyncCalls.add(call);
}
}
类中有是三个集合
Dequeue<AsyncCall> readyAsyncCalls = new ArrayQeueue<>();//正在准备的异步请求
Dequeue<AsyncCall> runningAsyncCalls = new ArrayQeueue<>();
//正在运行的异步请求
Dequeue<AsyncCall> runningSyncCalls = new ArrayQeueue<>();//
//正在运行的同步请求
executorService() 返回一个线程池(java当中的一个并发类)
if(executorService == null){
executorService = new ThreadPoolExecutor(0,Integer.MAIN_VALUE,60,TimeUnit.SECONDS,NEW SynchronourQueue<Runnable>(),Util.threadFactory("OkHttp Dispatcher",false));
}
return executorService;
网友评论