jason

// (1)创建 OkHttpClient 对象OkHttpClient client = new OkHttpClient();

// (2)创建 Request 对象

Request request = new Request.Builder()

.url(url)

.build();

// (3)创建 Call 对象。

Call call = client.newCall(request);

// (4)发送请求并获取服务器返回的数据

Response response = call.execute();

// (5)取出相应的数据

String data = response.body().string();

异步请求

jason

// (1)创建 OkHttpClient 对象OkHttpClient client = new OkHttpClient();

// (2)创建 Request 对象

Request request = new Request.Builder()

.url(url)

.build();

// (3)创建 Call 对象。

Call call = client.newCall(request);

// (4)发送请求并获取服务器返回的数据

call.enqueue(new Callback() {

@Override

public void onFailure(Call call, IOException e) {

}

@Override

public void onResponse(Call call, Response response) throws IOException {

// (5)取出相应的数据

String data = response.body().string();

}

});

二、源码分析


简易图

2.1OkHttpClient 对象

OkHttpClient(Builder builder) {

this.dispatcher = builder.dispatcher;

this.proxy = builder.proxy;

this.protocols = builder.protocols;

this.connectionSpecs = builder.connectionSpecs;

this.interceptors = Util.immutableList(builder.interceptors);

this.networkInterceptors = Util.immutableList(builder.networkInterceptors);

this.eventListenerFactory = builder.eventListenerFactory;

this.proxySelector = builder.proxySelector;

this.cookieJar = builder.cookieJar;

this.cache = builder.cache;

this.internalCache = builder.internalCache;

this.socketFactory = builder.socketFactory;

boolean isTLS = false;

for (ConnectionSpec spec : connectionSpecs) {

isTLS = isTLS || spec.isTls();

}

if (builder.sslSocketFactory != null || !isTLS) {

this.sslSocketFactory = builder.sslSocketFactory;

this.certificateChainCleaner = builder.certificateChainCleaner;

} else {

X509TrustManager trustManager = Util.platformTrustManager();

this.sslSocketFactory = newSslSocketFactory(trustManager);

this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);

}

if (sslSocketFactory != null) {

Platform.get().configureSslSocketFactory(sslSocketFactory);

}

this.hostnameVerifier = builder.hostnameVerifier;

this.certificatePinner = builder.certificatePinner.withCertificateChainCleaner(

certificateChainCleaner);

this.proxyAuthenticator = builder.proxyAuthenticator;

this.authenticator = builder.authenticator;

this.connectionPool = builder.connectionPool;

this.dns = builder.dns;

this.followSslRedirects = builder.followSslRedirects;

this.followRedirects = builder.followRedirects;

this.retryOnConnectionFailure = builder.retryOnConnectionFailure;

this.connectTimeout = builder.connectTimeout;

this.readTimeout = builder.readTimeout;

this.writeTimeout = builder.writeTimeout;

this.pingInterval = builder.pingInterval;

if (interceptors.contains(null)) {

throw new IllegalStateException("Null interceptor: " + interceptors);

}

if (networkInterceptors.contains(null)) {

throw new IllegalStateException("Null network interceptor: " + networkInterceptors);

}

}

new OkHttpClient()内部使用构造器模式初始化了一些配置信息:支持协议、任务分发器(其内部包含一个线程池,执行异步请求)、连接池(其内部包含一个线程池,维护connection)、连接/读/写超时时长等信息。

public Builder() {

dispatcher = new Dispatcher();// 分发器

protocols = DEFAULT_PROTOCOLS;// HTTP 协议

connectionSpecs = DEFAULT_CONNECTION_SPECS;// 传输层版本和连接协议

eventListenerFactory = EventListener.factory(EventListener.NONE);// 事件监听工厂

proxySelector = ProxySelector.getDefault();// 代理选择器

cookieJar = CookieJar.NO_COOKIES;// cookie

socketFactory = SocketFactory.getDefault();// socket 工厂

hostnameVerifier = OkHostnameVerifier.INSTANCE;// 主机名字确认

certificatePinner = CertificatePinner.DEFAULT;// 证书链

proxyAuthenticator = Authenticator.NONE;// 代理服务器身份验证

authenticator = Authenticator.NONE;// 源服务器身份验证

connectionPool = new ConnectionPool();// 连接池

dns = Dns.SYSTEM;// 域名

followSslRedirects = true;// 是否遵循 ssl 重定向

followRedirects = true;// 是否遵循重定向

retryOnConnectionFailure = true;// 连接失败的时候是否重试

connectTimeout = 10_000;// 连接超时

readTimeout = 10_000;// 读超时

writeTimeout = 10_000;// 写超时

pingInterval = 0;// HTTP / 2 和 Web 套接字 ping 之间的时间间隔

}

2.2 Request 对象

Request request = new Request.Builder()

.url(url)

.build();

/Request/

//…

final HttpUrl url;

final String method;

final Headers headers;

final @Nullable RequestBody body;

final Map<Class<?>, Object> tags;

//…

每一次网络请求都是一个Request,Request是对url,method,header,body的封装,也是对Http协议中请求行,请求头,实体内容的封装

通常我们通过构建折模式来构建一个Request对象来来设置一些请求链接(url)、请求方法(method)、请求头(headers)、请求体(body)、标签(tag,可作为取消请求的标记)

2.3 Call对象

Call call = client.newCall(request);

@Override public Call newCall(Request request) {

return RealCall.newRealCall(this, request, false /* for web socket */);

}

static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {

// Safely publish the Call instance to the EventListener.

RealCall call = new RealCall(client, originalRequest, forWebSocket);

call.eventListener = client.eventListenerFactory().create(call);

return call;

}

RealCall 是 Call 的实现类,Call 定义了请求相关的操作,例如同步异步、取消请求等方法。所以后续的请求相关操作基本都是在调用 Call 定义的方法,而这些方法真正的执行是它的实现类 RealCall

2.4请求数据

请求的整个预览图

同步请求 代码如下:

@Override public Response execute() throws IOException {

synchronized (this) {

if (executed) throw new IllegalStateException(“Already Executed”);

executed = true;

}

captureCallStackTrace();

eventListener.callStart(this);

try {

client.dispatcher().executed(this);// (1)

Response result = getResponseWithInterceptorChain();// (2)

if (result == null) throw new IOException(“Canceled”);

return result;

} catch (IOException e) {

eventListener.callFailed(this, e);

throw e;

} finally {

client.dispatcher().finished(this);// (3)

}

}

/Dispatcher/

synchronized void executed(RealCall call) {

runningSyncCalls.add(call);

}

// RealCall.java

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));

// originalRequest:我们写的 request

Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,

originalRequest, this, eventListener, client.connectTimeoutMillis(),

client.readTimeoutMillis(), client.writeTimeoutMillis());

return chain.proceed(originalRequest);

}

①根据上面源码我们可以知道getResponseWithInterceptorChain()返回了 Response ,由此可见访问网络从服务器获取数据的操作都在getResponseWithInterceptorChain()内

②这里引入了拦截器链,Request 需要通过拦截器链接收相应的处理最后才会发送到服务器并获取服务器返回的响应

拦截器执行顺序

  • 应用拦截器:开发者添加的拦截器

  • retryAndFollowUpInterceptor:负责失败重连操作,以及重定向,如果 call 被取消会抛出 IOException

  • BridgeInterceptor:作为网络层与应用层之间的桥梁,把(应用层请求)user request转化为(网络层请求)network request,然后向服务器发送network request,得到(网络层响应)network reseponse后转化为(应用层响应) user response

  • CacheInterceptor:处理缓存中的 requests 以及把 responses 写到缓存

  • ConnectInterceptor:负责与目标服务器建立连接

  • 网络拦截器:开发者添加的拦截器

  • CallServerInterceptor:拦截器链的最后一个拦截器,负责向服务器发送请求和从服务器获取响应数据

异步请求代码如下

// RealCall.java

@Override public void enqueue(Callback responseCallback) {

synchronized (this) { // 如果这个 call 已经被执行过,抛异常

if (executed) throw new IllegalStateException(“Already Executed”);

executed = true;

}

captureCallStackTrace();

eventListener.callStart(this);

client.dispatcher().enqueue(new AsyncCall(responseCallback));

}

AsyncCall call = new AsyncCall(responseCallback);

Dispatcher dispatcher = client.dispatcher();

dispatcher.enqueue(call);

把 responseCallback 封装成 AsyncCall

返回了一个 Dispatcher

调用任务调度器 Dispatcher 的 enqueue() 异步执行 call

解一下 Dispatcher

// Dispatcher.java

public final class Dispatcher {

// 同步请求和异步请求之和最大值

private int maxRequests = 64;

// 同一个 host 请求数最大值

private int maxRequestsPerHost = 5;

private @Nullable Runnable idleCallback;

/** Executes calls. Created lazily. */

/** 用于执行请求的线程池,且是懒加载的 */

private @Nullable ExecutorService executorService;

/** 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<>();

/** Running synchronous calls. Includes canceled calls that haven’t finished yet. */

/** 正在执行的同步请求,包括已经被取消但未完成的请求 */

private final Deque runningSyncCalls = new ArrayDeque<>();

public synchronized ExecutorService executorService() {

if (executorService == null) {

// 核心线程数为0,最大线程数为 Integer.MAX_VALUE ,空闲线程最多存活60秒

executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,

new SynchronousQueue(), Util.threadFactory(“OkHttp Dispatcher”, false));

}

return executorService;

}

synchronized void enqueue(AsyncCall call) {

if (runningAsyncCalls.size() < maxRequests

&& runningCallsForHost(call) < maxRequestsPerHost) {

// 如果正在执行的异步请求数没有达到最大值

// 就放到 runningAsyncCalls 标记为正在执行

runningAsyncCalls.add(call);

// 用 executorService 执行这个异步请求

executorService().execute(call);

} else {

// 如果正在执行的异步请求数达到最大值

// 就放到 readyAsyncCalls 标记为等待执行

readyAsyncCalls.add(call);

}

}

}

Dispatcher 是任务调度器,内部建立了一个线程池 ExecutorService ,而且维护了三个集合:

  • readyAsyncCalls : 等待被执行的异步请求集合

  • runningAsyncCalls : 正在执行的异步请求集合,包括已经被取消但未完成的请求

  • runningSyncCalls : 正在执行的同步请求集合,包括已经被取消但未完成的请求

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

如何成为Android高级架构师!

架构师必须具备抽象思维和分析的能力,这是你进行系统分析和系统分解的基本素质。只有具备这样的能力,架构师才能看清系统的整体,掌控全局,这也是架构师大局观的形成基础。 你如何具备这种能力呢?一是来自于经验,二是来自于学习。

架构师不仅要具备在问题领域上的经验,也需要具备在软件工程领域内的经验。也就是说,架构师必须能够准确得理解需求,然后用软件工程的思想,把需求转化和分解成可用计算机语言实现的程度。经验的积累是需要一个时间过程的,这个过程谁也帮不了你,是需要你去经历的。

但是,如果你有意识地去培养,不断吸取前人的经验的话,还是可以缩短这个周期的。这也是我整理架构师进阶此系列的始动力之一。


成为Android架构师必备知识技能

对应导图的学习笔记(由阿里P8大牛手写,我负责整理成PDF笔记)

部分内容展示

《设计思想解读开源框架》

  • 目录
  • 热修复设计
  • 插件化框架设计

    《360°全方面性能优化》
  • 设计思想与代码质量优化
  • 程序性能优化

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

,是需要你去经历的。

但是,如果你有意识地去培养,不断吸取前人的经验的话,还是可以缩短这个周期的。这也是我整理架构师进阶此系列的始动力之一。


成为Android架构师必备知识技能

[外链图片转存中…(img-l1EO7AbN-1713227313734)]

对应导图的学习笔记(由阿里P8大牛手写,我负责整理成PDF笔记)

[外链图片转存中…(img-MP8mq1aA-1713227313735)]

部分内容展示

《设计思想解读开源框架》

  • 目录
    [外链图片转存中…(img-dGVR1zgD-1713227313736)]
  • 热修复设计
    [外链图片转存中…(img-DFDc6Kun-1713227313737)]
  • 插件化框架设计
    [外链图片转存中…(img-tKH386Bi-1713227313737)]
    《360°全方面性能优化》
    [外链图片转存中…(img-h7hXULwR-1713227313738)]
  • 设计思想与代码质量优化
    [外链图片转存中…(img-iRp3jtkw-1713227313739)]
  • 程序性能优化
    [外链图片转存中…(img-roESDDdT-1713227313740)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐