OKHttp 解析
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OKHttp 解析相关的知识,希望对你有一定的参考价值。
参考技术A 分析网络访问框架的三个步骤,三个主线:1、请求发送到哪去了?
call.enqueue()------equeue()
访问统一目标机器请求个数值,默认为5
< 5 时 加入运行状态队列 ,否则加入等待状态队列
2、请求是被谁处理了?
executorService 线程池,核心线程是0,最大数是maxValue,线程池内部维护等待队列,OKHTTP中是一个无容量队列,相当于来到请求就必须处理,没有线程时就会创建,所以就会是maxValue。
然后就到AsyncCall类,调用里边的execute()方法,这是真正处理请求的地方,然后走到getResponsewithInterceptorChain()方法,里边是一个责任链模式,
责任链模式:有一条链子,链子上有多个节点,每个节点都有成功或失败两个结果,这样做的好处是,我们在访问服务器的时候,可以在里边进行过滤,拦截无效请求。
重试拦截器、桥拦截器、缓存拦截器、连接拦截器、网络拦截器、。。。
经过拦截过滤后,才会发送到服务器的请求。
3、请求是怎么被维护的?
client.dispatch
HTTP请求开始:
client=new OkHttpClient();
Request request=new Request.Builder().url("your url").build();
//同步发起请求
Response syncResponse=client.newCall(request).execute();
//异步发起请求
client.newCall(request).enqueue(newCallback()
@Override
public void onFailure(@NotNullCallcall,@NotNullIOExceptione)
@Override
public void onResponse(@NotNullCallcall,@NotNullResponseresponse)throwsIOException
);
调用过程:
new OKHTTPClient()-----》client.newCall(request)----->execute()同步请求------->RealCall#getResponseWithInterceptorChain( )--------->RealInterceptorChain#proceed(request)
new OKHTTPClient()-----》client.newCall(request)----->enqueue()异步请求-----》Dispatcher.equeue( )---
---->Dispatcher#promoteAndExecute( )------>executeOn( )----->run( )----------------------------------------------------------------->RealCall#getResponseWithInterceptorChain( )--------->RealInterceptorChain#proceed(request)
OKHTTP中有五种拦截器 :缓存拦截、网络连接拦截、
自定义拦截器的三个步骤:
chain.request()
chain.proceed()
return response;
OKHTTP可以配置x509trustManager,设置TLS信任证书:
这块有一个坑,就是必须先要接受系统的证书,然后接受本地证书。否则访问一些链接会出现异常。
OKHTTP的请求队列使用的是SynchronousQueue,这个队列的特点是容量为0,来到请求就马上处理
面试题1:OKHTTP中的责任链是怎样串联起来的?请求回来的数据进行怎样线程切换?
答:串联方式,通过将各种拦截器加入一个集合中,创建一个RealInterceptorChain对象,传入这个拦截器集合,传入一个index为0,他本质上是一个Chain子类,会内部回调proceed()回调方法,在proceed()方法中,循环创建RealInterceptorChain对象,index每次加1,每次取出一个拦截器,拦截器调用回调方法intercept(),内部进行拦截执行,完成自己能干的事,然后返回一个response,经过这种方式将各个拦截器的执行串联起来。
异步方式会调用enqueue()方法,里边client.dispatcher().enqueue(new AsyncCall(responseCallback));这个AsyncCall实质上是一个Runable,在Runable的run方法中,调用execute(),他是一个待实现的方法,在execute()的实现方法中,调用getResponseWithInterceptorChain(),里边就是对于请求的拦截,通过回调将结果返回给onResponse(),注意,这里的返回结果,OKHTTP并没有给我们切回主线程。接下来的操作就是由我们自己完成了,可以使用handler完成接下来的操作、或者runOnUIThread()切回主线程。
由子线程得到结果后,想要在主线程更新UI,可以使用三种方式:
(1)runOnUiThread():内部实际上是做了线程判断,如果是主线程,那么直接执行,否则的话,会利用Activity中的默认创建的handler来执行,会调用handler.post(),而这个post方法也会调用sendMessage()
(2)handler.post(new Runnable),使用handler方法切回主线程时,注意handler的实例化要放在主线程中,而不能在新开的子线程中,否则报错,这是因为,Handler在哪里创建,就获得哪里的Looper。主线程创建的Handler,即默认使用主线程的Looper。即能否更新UI主要是看Looper是否在主线程。因为Looper是在创建它的线程执行的。
handler.post()----->sendMessageDelayed(getPostMessage(r), 0);本质上和sendMessage()一样,都是发送一条消息。
(3)view.post(new Runnable),回判断view的attachInfo字段是否为空,如果不为空,则获取attachInfo中的Handler对象,然后调用handler的post方法来进行线程切换。
面试题2:Handler sendMessageDelay() 是怎样执行的?
sendMessageDelay()方法,会在当前时间加上延时时间,然后在MessageQueue类的enqueueMessage()方法中,将这个时间赋值给msg.when ,代表消息执行时间,然后轮询器Looper调用loop循环的时候,循环取出消息队列中的msg,然后调用messageQueue的next()方法取下一条消息。方法内部会用当前时间与msg.when对比,如果小于,说明未到执行时间,则拿到两者的差值,下一次循环的时候调用nativePollOnce()方法,Linux内部会对各个消息重排序。等到执行时间到了之后,将消息返回给Looper。
面试题3:Glide缓存,该怎样存?
面试题4:Retrofit实现机制,数据回来之后的线程切换?
Retrofit内部使用动态代理、注解、反射来实现接口的封装,使用okhttp实现实现请求操作,实际上,在Retrofit创建过程中,在build方法里,
if (callbackExecutor ==null)
callbackExecutor =platform.defaultCallbackExecutor();
而这个platform.defaultCallbackExecutor();调用了,
static final class androidextends Platform
Android()
super(Build.VERSION.SDK_INT >=24);
@Override
public ExecutordefaultCallbackExecutor()
return new MainThreadExecutor();
也就是创建了MainThreadExecutor()对象,
static final class MainThreadExecutor implements Executor
private final Handlerhandler =new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r)
handler.post(r);
MainThreadExecutor 是一个静态内部终类,实际上创建了一个Handler,,里边传入的是主线程的Looper,前面创建的callbackExecutor,就是实现请求数据返回的接口类,从而就可以实现将请求数据通过handler传回主线程。
面试题5:HTTPS 中的TLS属于哪层协议?
答:属于应用层与传输层之间的协议,
Okhttp底层是通过java的socket请求与接受响应,(因为HTTP就是基于TCP的),但是okhttp实现了连接池的概念,即对于同一主机的多个请求,其实可以共用一个socket连接,而不是每次发送完HTTP请求就关闭底层socket,这样就实现了连接池的概念,而okhttp对于socket的读写操作使用的OKIO库进行的一层封装。
以上是关于OKHttp 解析的主要内容,如果未能解决你的问题,请参考以下文章