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(); // 取消全部
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<Interceptor> 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 exceptions if (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()); // 更新cookie Response.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
OkHttp使用及流程分析
最新推荐文章于 2025-02-27 16:21:47 发布