最后
现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水!
为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!
Android架构师之路很漫长,一起共勉吧!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
-
第三部分:空行,请求头部后面的空行是必须的
-
第四部分:请求数据也叫主体,可以添加任意的其他数据。
一般情况下,服务器接收并处理客户端发过来的请求后会返回一个 HTTP 的响应消息。
HTTP 响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
简化如下:
1、客户端和服务端建立 SSL 握手,客户端通过 CA 证书来确认服务端的身份;
2、互相传递三个随机数,之后通过这随机数来生成一个密钥;
3、互相确认密钥,然后握手结束;
4、数据通讯开始,都使用同一个对话密钥来加解密;
-
1** 信息,服务器收到请求,需要请求者继续执行操作
-
2** 成功,操作被成功接收并处理
-
3** 重定向,需要进一步的操作以完成请求
-
4** 客户端错误,请求包含语法错误或无法完成请求
-
5** 服务器错误,服务器在处理请求的过程中发生了错误
套接字(socket)是通信的基石,是支持 TCP/IP 协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的 IP 地址,本地进程的协议端口,远地主机的 IP 地址,远地进程的协议端口。
意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。
使用场景: 1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 3、可动态指定一组对象处理请求。
在Android开发中,学过自定义view的应该也知道:ViewGroup 事件传递的递归调用就类似一条责任链,一旦其寻找到责任者,那么将由责任者持有并消费掉该次事件,具体体现在 View 的 onTouchEvent 方法中返回值的设置,如果 onTouchEvent 返回 false,那么意味着当前 View 不会是该次事件的责任人,将不会对其持有;如果为 true 则相反,此时 View 会持有该事件并不再向下传递。
下面开始为正文内容
=========================================================================
网络底层库,它是基于 http 协议封装的一套请求客户端,虽然它也可以开线程,但根本上它更偏向真正的请求,跟 HttpClient, HttpUrlConnection 的职责是一样的。其中封装了网络请求 get、post 等底层操作的实现。
-
OkHttp 提供了对最新的 HTTP 协议版本 HTTP/2 和 SPDY的支持,这使得对同一个主机发出的所有请求都可以共享相同的套接字连接。
-
如果 HTTP/2 和 SPDY 不可用,OkHttp 会使用连接池来复用连接以提高效率。
-
OkHttp 提供了对 GZIP 的默认支持来降低传输内容的大小。
-
OkHttp 也提供了对 HTTP 响应的缓存机制,可以避免不必要的网络请求
-
当网络出现问题时,OkHttp 会自动重试一个主机的多个 IP 地址。
=======================================================================
implementation(“com.squareup.okhttp3:okhttp:3.10.0”)
-
1.先创建 OkHttpClient 实例;
-
2.构造 Request 实例,传入 url 等相关参数;
-
3.通过前两步中的实例对象构建 Call 对象;
-
4.异步请求通过 Call#enqueue(Callback) 方法来提交异步请求,同步请求通过 Call#execute() 直接 获取Reponse
相应代码如下
//1.创建⼀个 OkHttp 的实例
OkHttpClient client = new OkHttpClient.Builder().build();
//2.创建 Request
Request request = new Request.Builder().url(“http://www.jimengjia.com”).build();
//3.构建 Call 对象
Call call=okHttpClient.newCall(request);
//4.通过 Call#enqueue(Callback) 方法来提交异步请求
call.enqueue(new Callback() {
@Override
public void onFailure( Call call, IOException e) {
}
@Override
public void onResponse( Call call,Response response) throws IOException {
}
});
看源码的流程(思想):
1.从使用步骤中第四步可以看出起关键作用的是enqueue(),所以从源码中找到此方法开始分析。
代码如下:
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
//每个请求只能执行一次
if (executed) throw new IllegalStateException(“Already Executed”);
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
//进入下一个主线
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
2.从上述代码可以看到,创建了一个 AsyncCall 并将Callback传入后,最后交给了任务分发器 Dispatcher 来进一步处理。
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);
}
}
相应的对象如下:
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
//可以很明显看出是添加到了runningAsyncCalls,readyAsyncCalls中
/** Ready async calls in the order they’ll be run. */
private final Deque readyAsyncCalls = new ArrayDeque<>();
/** Running asynchronous calls. Includes canceled calls that haven’t finished yet. */
private final Deque runningAsyncCalls = new ArrayDeque<>();
此方法的大致内容:对请求的入队做了一些限制,若正在执行的请求数量小于最大值(默认64),并且此请求所属主机的正在执行任务小于最大值(默认5),就加入正在运行的队列并通过线程池来执行该任务,否则加入准备执行队列中。
3.从上述代码可以看到,当满足条件后将进入executorService()
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue(), Util.threadFactory(“OkHttp Dispatcher”, false));
}
return executorService;
}
这里的具体就是放到线程池里的运行了。(以下内容为拓展)
ExecutorService的创建方式如下:所有线程池最终都是通过这个方法来创建的。
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
BlockingQueue workQueue,ThreadFactory threadFactory,
RejectedExecutionHandler handler)
-
corePoolSize :核心线程数,一旦创建将不会再释放。如果创建的线程数还没有达到指定的核心线程数量,将会继续创建新的核心线程,直到达到最大核心线程数后,核心线程数将不在增加;如果没有空闲的核心线程,同时又未达到最大线程数,则将继续创建非核心线程;如果核心线程数等于最大线程数,则当核心线程都处于激活状态时,任务将被挂起,等待空闲线程来执行。
-
maximumPoolSize :最大线程数,允许创建的最大线程数量。如果最大线程数等于核心线程数,则无法创建非核心线程;如果非核心线程处于空闲时,超过设置的空闲时间,则将被回收,释放占用的资源。
-
keepAliveTime : 也就是当线程空闲时,所允许保存的最大时间,超过这个时间,线程将被释放销毁,但只针对于非核心线程。
-
unit : 时间单位,TimeUnit.SECONDS等。
-
workQueue : 任务队列,存储暂时无法执行的任务,等待空闲线程来执行任务。
-
threadFactory : 线程工程,用于创建线程。
-
handler : 当线程边界和队列容量已经达到最大时,用于处理阻塞时的程序
可以明显的看到创建时使用的队列为SynchronousQueue:它内部没有容器(可以去拓展一下,本文就不写了)
4.进入到下一个代码区execute():
@Override protected void execute() {
boolean signalledCallback = false;
try {
//处理请求的地方
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
responseCallback.onFailure(RealCall.this, new IOException(“Canceled”));
} else {
signalledCallback = true;
//回调将结果返回调用者
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
eventListener.callFailed(RealCall.this, e);
//如果发生异常产生错误回调
responseCallback.onFailure(RealCall.this, e);
}
} finally {
//维护,执行完之后,调用dispatcher中的finish函数
client.dispatcher().finished(this);
总结
开发是面向对象。我们找工作应该更多是面向面试。哪怕进大厂真的只是去宁螺丝,但你要进去得先学会面试的时候造飞机不是么?
作者13年java转Android开发,在小厂待过,也去过华为,OPPO等,去年四月份进了阿里一直到现在。等大厂待过也面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。
这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
相信它会给大家带来很多收获:
资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-21vxw702-1714999724421)]
[外链图片转存中…(img-8P751kxi-1714999724422)]
资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!