- 首页 > it技术 > >
- get & post
1.1 组装Get or Post请求
Request requestGet = new Request.Builder().url(url).build();
// 其他request可选项
//.tag(tag)
//.header(key, value)
//.cacheControl(CacheControl.FORCE_NETWORK)
//.method(METHOD_GET, null)
Request requestPost = new Request.Builder().url(url).post(requestBody).build();
RequestBody:
FormBody formBody = new FormBody.Builder().add(key, value).build();
// 提交表单,使用默认MediaType application/x-www-form-urlencoded
RequestBody fileBody = RequestBody.create(MediaType.parse(""), file);
// 提交文件(上传文件)
RequestBody body = RequestBody.create(MediaType.parse("application/json;
charset=utf-8"), json.toString);
// 提交Json
MultipartBody.Builder.setType(MultipartBody.FORM).addPart(key, value).addPart(fileBody).build();
// 提交表单和文件
1.2 发送请求
Call call = new OkHttpClient.Builder().build().newCall(request);
非Async方式:
Response response = call.execute();
Async方式:
call.enqueue(new Callback() {
onFailure(Call call, IOException e){非UI线程}
onResponse(Call call, Response response){非UI线程}
});
- 下载文件 & 图片显示
同1中的使用方式,组装请求后发送,拿到Response或者在Callback中对Response做进一步处理。
ResponseBody body = Response.body();
InputStream is = body.byteStream();
// 获取response的InputStream流,这个用于直接read然后保存在文件(下载)或者Bitmap中。
byte[] bytes = body.bytes();
// 获取response的byte数据
Reader reader = body.charStream();
String string = body.string();
- 取消
Call call;
call.cancel();
对于同一个OkHttpClient中的Call,可以在dispatcher中进行遍历查询。
for (Call call: client.dispatcher().queuedCalls()) {
if (call.request().tag() == TAG) {} // 根据tag判断
if (call.request().url() == URL){} // 根据url判断
if (call.request().header(key) == VALUE){} // 根据header判断
}
for (Call call: client.dispatcher().runningCalls())
client.dispatcher().cancelAll();
// 取消全部
- 【OkHttp使用及流程分析】OkHttpClient的设置(OkHttpClient.Builder)
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;
connectionSpecs = DEFAULT_CONNECTION_SPECS;
eventListenerFactory = EventListener.factory(EventListener.NONE);
proxySelector = ProxySelector.getDefault();
cookieJar = CookieJar.NO_COOKIES;
socketFactory = SocketFactory.getDefault();
hostnameVerifier = OkHostnameVerifier.INSTANCE;
certificatePinner = CertificatePinner.DEFAULT;
proxyAuthenticator = Authenticator.NONE;
authenticator = Authenticator.NONE;
connectionPool = new ConnectionPool();
dns = Dns.SYSTEM;
followSslRedirects = true;
followRedirects = true;
retryOnConnectionFailure = true;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
}
@Nullable Proxy proxy;
final List interceptors = new ArrayList<>();
final List networkInterceptors = new ArrayList<>();
@Nullable Cache cache;
@Nullable InternalCache internalCache;
@Nullable SSLSocketFactory sslSocketFactory;
@Nullable CertificateChainCleaner certificateChainCleaner;
- Call的执行流程
5.1 RealCall
创建RealCall并执行RealCall中的execute或enqueue方法
class RealCall {
final OkHttpClient client;
final RetryAndFollowUpInterceptor retryAndFollowUpInterceptor;
Response execute() {
try {
client.dispatcher().executed(this);
// dispatcher.runningSyncCalls.add(call);
ArrayDeque来保存runningCalls
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} finally {
client.dispatcher().finished(this);
}
}void enqueue(Callback callback) {
client.dispatcher().enqueue(new AsyncCall(responseCallback));
// dispatcher.runningAsyncCalls.add(call);
ArrayDeque来保存runningCalls。
//dispatcher中使用ExecutorService维护了一个线程池,来执行Runnable
}class AsyncCall extends NamedRunnable {
void execute() {
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
responseCallback.onResponse(RealCall.this, response);
}
}
}Response getResponseWithInterceptorChain() {
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);
}
}
5.2 RealInterceptorChain & Interceptor
index = 0
Response proceed(Request) {
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, connection, index + 1, request);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
}
(client.interceptors)
index = 1
// This interceptor recovers from failures and follows redirects as necessary.负责失败重试及重定向
RetryAndFollowUpInterceptor.intercept(Chain chain) {
Response priorResponse = null;
while (true) {
// 调用Chain的proceed,调用下一个Interceptor
response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
// RouteException, IOException 等不再重试,throw exceptionsif (priorResponse != null) { // Attach the prior response if it exists. Such responses never have a body.
response = response.newBuilder()
.priorResponse(priorResponse.newBuilder()
.body(null)
.build())
.build();
}Request followUp = followUpRequest(response);
// 拿到新的Request(重定向或重试)if (followUp == null) { // 没有新的request了,返回response
return response;
}if (!sameConnection(response, followUp.url())) { // 如果重定向了,使用新的StreamAllocation
streamAllocation.release();
streamAllocation = new StreamAllocation(client.connectionPool(), createAddress(followUp.url()), callStackTrace);
}request = followUp;
priorResponse = response;
// 保存此次的Response为prior, 保存followUp作为新的request,进入循环
}}index = 2
// Bridges from application code to network code. First it builds a network request from a user
// request. Then it proceeds to call the network. Finally it builds a user response from the network
// response.
// 负责把用户构造的请求转换为发送到服务器的请求,把服务器端返回的响应转换为用户友好的响应。
BridgeInterceptor.intercept(Chain chain) {
// request转换
Request userRequest = chain.request();
Request.Builder requestBuilder = userRequest.newBuilder();
RequestBody body = userRequest.body();
// add or remove Header(根据原request参数判断是否增加)
requestBuilder.header("Content-Type", contentType.toString());
requestBuilder.header("Content-Length", Long.toString(contentLength));
requestBuilder.removeHeader("Transfer-Encoding");
requestBuilder.header("Host", hostHeader(userRequest.url(), false));
requestBuilder.header("Connection", "Keep-Alive");
requestBuilder.header("Accept-Encoding", "gzip");
//
requestBuilder.header("Cookie", cookieHeader(cookies));
requestBuilder.header("User-Agent", Version.userAgent());
// 转换request完毕,使用新的request继续执行
Response networkResponse = chain.proceed(requestBuilder.build());
// response转换
HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());
// 更新cookieResponse.Builder responseBuilder = networkResponse.newBuilder().request(userRequest);
if (transparentGzip
&& "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
&& HttpHeaders.hasBody(networkResponse)) {
GzipSource responseBody = new GzipSource(networkResponse.body().source());
Headers strippedHeaders = networkResponse.headers().newBuilder()
.removeAll("Content-Encoding")
.removeAll("Content-Length")
.build();
responseBuilder.headers(strippedHeaders);
responseBuilder.body(new RealResponseBody(strippedHeaders, Okio.buffer(responseBody)));
}// 返回转换后的新response
return responseBuilder.build();
index = 3
// Serves requests from the cache and writes responses to the cache.
// 从cache取request,将Response保存到cache
CacheInterceptor.intercept(Chain chain) {
// 先调用Cache,拿到Response
Response cacheCandidate = cache != null ? cache.get(chain.request()) : null;
// 根据Cache策略判断能否使用cache,能否使用network
// 如果不能使用network,则返回cacheResponse或者错误response// 调用网络
Response networkResponse = chain.proceed(networkRequest);
// 如果有CacheResponse,根据条件决定返回
if (cacheResponse != null) {
if (networkResponse.code() == HTTP_NOT_MODIFIED) {
// 返回CacheResponse
}
}// 使用networkResponse
Response response = networkResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse))
.networkResponse(stripBody(networkResponse))
.build();
// 如果支持Cache,保存Response到Cache
cacheWritingResponse(cacheRequest, response);
}index = 4
// Opens a connection to the target server. 创建一个到Server端的Connection,HttpCodec,然后传到下一个拦截器
ConnectInterceptor.intercept(Chain chain) {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Request request = realChain.request();
StreamAllocation streamAllocation = realChain.streamAllocation();
// We need the network to satisfy this request. Possibly for validating a conditional GET.
boolean doExtensiveHealthChecks = !request.method().equals("GET");
HttpCodec httpCodec = streamAllocation.newStream(client, doExtensiveHealthChecks);
RealConnection connection = streamAllocation.connection();
return realChain.proceed(request, streamAllocation, httpCodec, connection);
}(client.networkInterceptors)
index = 5
// This is the last interceptor in the chain. It makes a network call to the server.这个最后一个拦截器,负责真正和server端交互。
CallServerInterceptor.intercept(Chain chain) {
...
Response response = responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
...
}
- 项目地址
https://github.com/guolina02/HttpDemo
推荐阅读