本着针对面试负责任的态度,记录面试过程中各个知识点,而不是入门系列,如果有不懂的自行学习。
目前总结了以下几个方面:
- Android优化
- HashMap分析
- Handler源码分析
- OkHttp分析
- Retrofit分析
- 自定义View
由于篇幅原因拆分成两个部分分享,上一篇讲解了前面三个方面,今天讲剩下的三个部分,之后的还会持续更新。
OkHttp分析
Okhttp是对Socket的封装。有三个主要的类,Request,Response,Call默认使用new OkHttpClient() 创建初client对象。
如果需要初始化网络请求的参数,如timeout,interceptor等,可以创建Builder,通过builder.build() 创建初client对象。
使用new Request.Builder().url().builder()创建初requst对象。
通过client.newCall()创建出call对象,同步使用call.excute(), 异步使用call,enqueue(). 这里Call是个接口,具体的实现在RealCall这个实现类里面。
Okhttp的高效体现在,okhttp内有个Dispatcher类,是okhttp内部维护的一个线程池,对最大连接数,host最大访问量做了初始定义。维护3个队列及1个线程池
readyAsyncCalls
待访问请求队列,里面存储准备执行的请求。
runningAsyncCalls
异步请求队列,里面存储正在执行,包含已经取消但是还没有结束的请求。
runningSyncCalls
同步请求队列,正在执行的请求,包含已经取消但是还没有结束的请求。
ExecutorService
线程池,最小0,最大Max的线程池
在执行call.excute()的时候,调用到realcall类里的excute方法,这个是同步方法,在方法的第一行就加了锁,判断executed标记,如果是true就抛出异常,保证一个请求只被执行一次。false的话继续向下执行。调用client.dispatcher.excute()进入到dispatcher类中,向runningSyncCalls队列中添加当前这个请求。执行结束会调用finished方法
如果是异步操作,会创建一个RealCall.AsyncCall对象,AsyncCall继承的NamedRunnable接口,NamedRunnable是个runnable。进入到Dispatcher的enqueue()方法中,首先判断线程池中线程的数据,host的访问量,如果都没有达到那么加入到runningAsyncCalls中,并执行。否则加入到readyAsyncCalls队列中。
finished方法,如果是异步操作,promoteCall方法,promoteCalls()中用迭代器遍历readyAsyncCalls 然后加入到runningAsyncCalls
RealConnection
真正的连接操作类,对soket封装,http1/http2的选择,ssl协议等等信息。一个recalconnection就是一次链接
ConnectionPool
链接池,管理http1/http2的连接,同一个address共享一个connection,实现链接的复用。
StreamAlloction
保存了链接信息,address,HttpCodec,realconnection,connectionpool等信息
在realCall中 getResponseWithInterceptorChain()创建并开启拦截器链
Okhttp中的拦截器,默认的分为5种
- RetryAndFollowUpInterceptor
做网络失败重连,但是并不是所有的请求都需要重连,根据响应码。MAX_FOLLOW_UPS=20最大重连次数
在intercept方法中创建了StreamAllocation对象,并调用chain.proceed方法,执行下一个拦截器,对request进行处理,并返回response。 - BirdgeInterceptor
初始化信息,添加请求头等,例如gzip,keep-alive,返回的response进行解压 - CacheInterceptor
内部有Cache类,处理缓存操作,intercache内部类,disklrucache算法等
重点是不缓存非g