结尾
最后小编想说:不论以后选择什么方向发展,目前重要的是把Android方面的技术学好,毕竟其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。
当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。
高级UI,自定义View
UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。
不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
//这两个比较重要,等下会具体研究,它们大概就是对连接过程中的每一个阶段做处理
final List interceptors;
final List networkInterceptors;
//就是监听整个网络请求+返回过程
final EventListener.Factory eventListenerFactory;
//用处不大,不用了解了
final ProxySelector proxySelector;
//Jar是罐子的意思,CookieJar是存放Cookie的容器
final CookieJar cookieJar;
//Http的Cache
final @Nullable Cache cache;
final @Nullable InternalCache internalCache;
//Socket是Tcp的端口,这个就是Tcp端口的工厂
final SocketFactory socketFactory;
//Https下Tcp的端口
final @Nullable SSLSocketFactory sslSocketFactory;
//证书链,方便验证(https讲过)
final @Nullable CertificateChainCleaner certificateChainCleaner;
//Https验证的 主机名验证器, 验证对方的Host是不是想要访问的Host
final HostnameVerifier hostnameVerifier;
//直译叫证书固定器,用来做自签名,用来验证证书公钥,如果host的证书和这个对象传入(本地存的)的公钥一致,则证明对方是自己想要访问的一方。
final CertificatePinner certificatePinner;
//用来写 Authorization Bearer<…> 当权限不足的时候会报错 401
final Authenticator proxyAuthenticator;
final Authenticator authenticator;
//线程连接池,可以有那么多的线程可以用来进行网络请求
final ConnectionPool connectionPool;
//DNS实现类
final Dns dns;
//重定向跳转, 默认为true,即跳转
final boolean followRedirects;
//https跳到http重定向,默认为true
final boolean followSslRedirects;
//当连接建立失败后,是否重试,默认为true
final boolean retryOnConnectionFailure;
//Tcp连接、读、写 超过该时间就跑错
final int connectTimeout;
final int readTimeout;
final int writeTimeout;
//长连接,发送ping(相当于一个心跳)的时间间隔
final int pingInterval;
看完上面的配置还有一些注释,会很明白HTTP在OkHttp里面的配置,比较全而且清晰。
OkHttpClient
这个大总管它有关于Http、Https基本都有的配置信息,基本都是Header和Header有关的一些东西。
getResponseWithInterceptorChain()
OkHttp最核心的方法,相当于内部的入口。所以很有必要去了解。
我们先点进这个方法:
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
//第一部分
List interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
//第二部分
Interceptor.Chain chain = new RealInterceptorChain(
interceptors, null, null, null, 0, originalRequest);
//第三部分
return chain.proceed(originalRequest);
}
上面比较“麻雀虽小五脏俱全”的感觉,代码没那么多,但每一行都是核心。
它大概有三个部分:
-
装一些
Interceptor
到List中 -
构建一个
Interceptor Chain
-
使用chain的
proceed(originalRequest)
得到了网络响应的Response
我们用图分别来说下他们的概念:
首先这个方法会创建一个含有泛型为Interceptor
的List,并往这个List里面add几个系统自带的Interceptor。如上图所示。
而chain
的构造方法中带了这个List,也就是说,这个chain它其实是给这个List里的所有interceptor用一条链,按顺序给链了起来,如下图:
↑而且实际上,这条链并不是单向的,它走到走后的Interceptor后,会往回走。
原因很简单,chain的方向就是我们Request走的方向,我们把Request带过去(发送请求),最后会把Respnse带回来,回来的时候,也要这些Interceptor来处理结果。这就是chain。
为什么要用Chain和Interceptor,为什么不直接发到另一端去
那肯定是细节化啊。
万一你突然Request少了一个重要东西,我有必要在检查少了东西的这个环节进行上报,如果直接传过去,可能会产生不必要的开销。
chain的目的在于每个Interceptor都能够自定义的去处理这些事情,所以chain和Interceptor是多么滴重要。
process(request)
是做什么的呢?process是前进的意思。
概述:将Request
交个下一个Interceptor处理
将代码和图来讲一下:
它有三个情况,一个是将requeset,传过去,一个是等,一个是request/response回来:
(1)执行proceed()方法
Interceptor1
的时候执行了proceed(request),将request传给Interceptor2
(2)等Chain回来
(3)Chain回来了,得到Interceptor2给Interceptor的东西了,就可以去处理这个东西了
每个节点都会这样走,并且他们有做实际的对Request的操作(比如传Request之前,我们要作什么,拿回来Response后,我们要做什么)。所以按照顺序,我们来看下getRespnseWithInterceptorChain()里面的Interceptor
List interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
首先 interceptors.addAll(client.interceptors());
和 interceptors.addAll(client.networkInterceptors());
是用来加我们自定义的Interceptor(如果没有自定义,这个就是空的)的,别的Interceptor都是OkHttp自带的,我们后面再讲自定义的,先来看下OkHttp自带的Interceptor。
retry就是重试,FollowUp就是重定向。我们来看下它的源码:
而每个Interceptor最重要的方法就是它们的intercept(Chain)
方法,这个方法就是和上面一样做这些事情:
①处理别人给我的request1
,处理完后变成request2
②执行 chain.process(request2
)
③等待别的Interceptor处理完,给我传Response
④处理这个Response
就是会有一个模板代码:
//Interceptor的 intercept的模板代码
public Response intercept(Chain chain) {
//获取requeset
Request request = chain.requeset();
//前置方法,处理Requeset
…
response = chain.process(requeset);
//后置方法,处理Response
…
}
OK,看完这些,我们来看关于处理重定向的Interceptor的源码:
@Override public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//StreamAllocation: Streams是OkHttp中一个很重要的概念,它的含义是http连接时产生Request/Response对
streamAllocation = new StreamAllocation(
client.connectionPool(), createAddress(request.url()), callStackTrace);
…
while (true) {
…
try {
response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
releaseConnection = false;
} catch (RouteException e) {
// The attempt to connect via a route failed. The request will not have been sent.
if (!recover(e.getLastConnectException(), false, request)) {
throw e.getLastConnectException();
}
…
if (followUp == null) {
if (!forWebSocket) {
streamAllocation.release();
}
return response;
}
…
process()
方法其实是一个递归,一个Interceptor走了process(),那么这个process()方法就是给它的下一个Interceptor走process()…直到最后走完返回来,它得到的Response其实就是它后面全部走完后得到,返回的Response。
当我们重定向的Interceptor出现了需要重定向的时候,就会走代码中catch{}
,cover()
方法其实就是重定向的方法,它根据OkHttp的配置(比如之前看过的 retryOnConnectionFailure
的字段,如果是false,就不会进行重定向了…)然后根据这些配置去改变Request,更改地址信息,最终得到结果。
这个方法是while(true)包裹的,所以,它如果出现了重定向,一定会循环走。
重定向的Interceptor嘛…主要都是把精力集中在后置代码上。比较清楚的知道它在干什么。
我们来看下一个Interceptor把。
BridgeInterceptor(client.cookieJar())
桥接Interceptor。
往下看:
直到proceed()方法前,我们一目了然桥接Interceptor的前置方法,就是在给Http报文添加 请求头 Headers
它会添加ContentType、Content-Length、User-Agent…
需要注意的是,上面Accpet-Encodeing
中,如果我们没有自定义接收编码格式,OkHttp会默认是gzip
。
你都给我默认gzip,万一我自己解不了gzip怎么办,没问题,OkHttp会自己解析gzip(就在这边的后置代码中)~
而后置代码都是对数据Response的解析一遍。,这就是BridgeInterceptor()
CacheInterceptor(client.internalCache())
不就是Cache吗。
Cache方法里面会先创建一个CacheStrategy
,然后根据这个实例去查看拿来的Request它有没有Response(就是在本地有没有Cache)
↓如果我们本地有cache了,那我们就不用再去做网络请求了,这个时候会直接return 伪造一个Response给上个在等proceed()方法的Interceptor。
总结:
-
如果对于这个Request有cache,并且这个cache没有过期,则CacheInterceptor不会走proceed()方法,会直接返回cache的Response。
-
如果没有cache,才会走proceed()方法,走之后的网络请求。
从这里也可以看出,Interceptor有它分出来的好处。
这个地方是真正的和TCP、TLS做交互的地方,就是做连接的地方,它最主要的代码是下面:
通过newStream()
能得到一个HttpCodec
对象,它用于编码与解码(Http1.1用的是纯文本和http2.0用的是纯二进制)
connection()
里面会去建立Tcp连接(里面会走 connectSocket()
啊connectTLS()
方法)。
之前的OkHttpClient
配置全都在RealConnection()用到了。
该Interceptor几乎是最后一个Interceptor,因为它做了连接,所以它没有后置方法,直接返回response。
这个Interceptor没有proceed(),因为它做了实质了工作
它就是做请求的写,写在了Socket
中。
然后就是做响应的读,读成了一个ResponseBody
最后就返回这个包裹着 ResponseBody
的Response
了。
总结
大致就已经大概走完了Interceptor了,就是和一开始的那副chain图一样,request在各种拦截器里面被修改,最后变成了一个最终版的Request,然后发送出去。最后通过连接Tcp、TLS完后通过I/O流去读写,读回来一个Response,最后返回去。
我们在getResponseWithInterceptorChain()看到可以去自定义拦截器:
Response getResponseWithInterceptorChain() throws IOException {
…
//自定义的request
interceptors.addAll(client.interceptors());
…
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
…
}
我们可以在外面通过 addInterceptor去添加自定义的拦截器,和模板代码一样:
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
//前置工作
…
Response response = chain.proceed(chain.request())
//后置工作
…
return null;
}
}).build();
最后
简历首选内推方式,速度快,效率高啊!然后可以在拉钩,boss,脉脉,大街上看看。简历上写道熟悉什么技术就一定要去熟悉它,不然被问到不会很尴尬!做过什么项目,即使项目体量不大,但也一定要熟悉实现原理!不是你负责的部分,也可以看看同事是怎么实现的,换你来做你会怎么做?做过什么,会什么是广度问题,取决于项目内容。但做过什么,达到怎样一个境界,这是深度问题,和个人学习能力和解决问题的态度有关了。大公司看深度,小公司看广度。大公司面试你会的,小公司面试他们用到的你会不会,也就是岗位匹配度。
选定你想去的几家公司后,先去一些小的公司练练,学习下面试技巧,总结下,也算是熟悉下面试氛围,平时和同事或者产品PK时可以讲得头头是道,思路清晰至极,到了现场真的不一样,怎么描述你所做的一切,这绝对是个学术性问题!
面试过程一定要有礼貌!即使你觉得面试官不尊重你,经常打断你的讲解,或者你觉得他不如你,问的问题缺乏专业水平,你也一定要尊重他,谁叫现在是他选择你,等你拿到offer后就是你选择他了。
金九银十面试季,跳槽季,整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
可以讲得头头是道,思路清晰至极,到了现场真的不一样,怎么描述你所做的一切,这绝对是个学术性问题!
面试过程一定要有礼貌!即使你觉得面试官不尊重你,经常打断你的讲解,或者你觉得他不如你,问的问题缺乏专业水平,你也一定要尊重他,谁叫现在是他选择你,等你拿到offer后就是你选择他了。
金九银十面试季,跳槽季,整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
[外链图片转存中…(img-FqlJob4D-1715607090973)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!