Android开发除了flutter还有什么是必须掌握的吗?
相信大多数从事Android开发的朋友们越来越发现,找工作越来越难了,面试的要求越来越高了
除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
// 4. Certificate pinning must match the host.
try {
address.certificatePinner().check(address.url().host(), handshake().peerCertificates());
} catch (SSLPeerUnverifiedException e) {
return false;
}
return true; // The caller’s address can be carried by this connection.
}
解读一下这段代码:
- 返回值: 如果这个连接可以给这个访问地址一个流,那么返回true。(可见,判断连接是否可用,会考虑当前访问的ip地址是否匹配,很好理解,如果访问的ip都不一样,我凭什么把现成的连接给你复用。)
然后是众多if判断(这里存在一个
当前连接
与目标地址
的参数值对比),总结起来:
- 连接到达最大并发流或者连接不允许建立新的流,那就不允许复用;
- 如果地址的非host字段没有完全相同,也不允许复用。(解释一下,一个Address对象包含了host字段和其他字段,这里的非host字段,就是指的这个类中的其他字段)
- 如果到了这里,那就判断host是不是相同,如果相同,那就允许复用。
- 如果上面的3步判断都没有命中,那么,我们依然有机会去复用,只要不命中下面的判断。
1)HTTP2连接为空,不允许复用
2)使用了代理,并且代理的类型不是直接代理 或者 ,不允许复用
3)此连接的服务器证书必须覆盖新主机,否则也不能复用
4)证书固定必须与主机匹配,否则,也不能复用
上面的4个if都没有命中,那么还是判定为可以复用。
总结:如果在连接池中找到个连接参数一致并且未被关闭没被占用的连接,则可以复用旧连接,无需新建连接。
5. 服务调用拦截器 CallServerInterceptor
经历了 上面4个拦截器,我们最终拿到了 request
,connection
,有了请求,有了连接,那么就可以向服务器发起网络请求了。这一步,就包含执行网络请求的具体逻辑。
注意:我们这里的
request
,它是一个java
对象,但是底层用的TCP
协议,发送的是报文(在http1.X下,报文全都是明文字符串格式拼接,那么你一个request
对象中包含的内容如何去拼接成一个 报文字符串呢?)
反过来想,我们TCP
底层从服务器取得的也最先是 响应报文,他也是一大串字符串,那么如何封装成java
需要的Response
对象呢?逻辑也在这里。具体在哪个类?
HttpCodeC.java
在这里我关心两个问题:
1)真正与底层发生socket
网络通信是如何进行的?
2)httpCodeC
是如何解析request
成请求报文,又是如何将相应报文变成Response
的?
来探索,首先进入到CallServerInterceptor
的Interceptor
方法,这是核心入口:
首先回顾一下TCP socket通信的过程:
1)建立Socket
连接
2)打开IO
流通道(socket
是双工通讯协议,可以同时调用输入和输出流)
3)在这个案例中,移动端作为客户端需要往IO流通道中去写数据,然而我们知道,OutputStream
,当我们写了数据之后,必须调用flush
,刷新缓存区,才能将数据发送过去。
这里,我们就能得出上面一个问题的答案:
Q:真正与底层发生socket网络通信是如何进行的?
A:OkHttp使用了 OkIo来发送数据给远端,在这个Intercept
方法中,我们可以找到两句代码:httpCodec.flushRequest();
和httpCodec.finishRequest();
如果你进去看实现,会发现,他们执行的是同一个
flush
过程,将缓存去数据发送给远端。(至于更细节的,比如 sink.flush是如何实现的,我就不去探索了,有兴趣的可以继续深入)
下面来探究问题2:
Q: httpCodeC是如何解析request
成请求报文,又是如何将相应报文变成Response
的?
继续在Intercept
方法中寻找,发现:
httpCodec.writeRequestHeaders(request); //写入请求头
httpCodec.createRequestBody(request, contentLength) //构建请求体
深入可以发现,这两个方法其实都是接口方法,他们的具体实现分为了http1 和http2 ,两者实现并不相同,我们只看http1的:
看到了吧,这里其实就是在利用 io通道sink
来写入字符串而已。至此,request变成字符串报文已经有答案了。
那么,报文如何变成response
对象呢?
响应,分为响应头和响应体,先看响应头:
可以看出,响应头,是利用通道中读取出来的响应行,解析成StatusLine
对象,然后将StatusLine
对象的属性逐一读取,构建一个Response
对象。
那么响应体呢?
上图中,利用了OkIo
来缓存source
通道中的数据,构建一个RequestBody
对象。
现在有了ResponseHeader
和ResponseBody
,就能组成一个完整的Response
对象。
最后的结论:
CallServerInterceptor
拦截器 就是真正向远端socket发送数据以及 接收远端socket数据的一层,利用OkIO
作为数据通道。HTTP1
中以字符串拼接的方式,解析Request
数据然后发送 / 解析响应报文并封装成Response
对象.
#结语
OkHttp
作为知名第三方开源框架的佼佼者,其中值得探索学习的细节非常至多。但是我们学习框架,探索源码,一定要有自己的明确的目标。网上介绍okhttp
的文章很多,每个人的侧重点都不一样,但是okhttp
的大思想都是一样,比如:分发器/拦截器,分发器的三个双端队列的作用,5大系统拦截器的职责,责任链模式设计思路。
一定有人会说,上面文章的这么多细节,我是可以根据你的文章看一遍,走一遍,能够在脑子里留个印象,但是过两天又忘了,怎么办?
大可不必担忧,自己走过一遍的路,想要走第二遍,手到擒来,但是如果是完全没有走过的路,就是完全的陌生区域,会发生什么事,你完全把控不了。
程序员修炼路遥遥,深入学习过源码,和完全没看过源码,是截然不同的两个境界。
(PS:缓存拦截器的具体细节,后面有时间会出文章补上!)
总结
开发是面向对象。我们找工作应该更多是面向面试。哪怕进大厂真的只是去宁螺丝,但你要进去得先学会面试的时候造飞机不是么?
作者13年java转Android开发,在小厂待过,也去过华为,OPPO等,去年四月份进了阿里一直到现在。等大厂待过也面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。
这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
相信它会给大家带来很多收获:
资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
bs.csdn.net/topics/618156601)**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!