Android Okhttp浅析
来源:互联网 发布:二阶转置矩阵公式 编辑:程序博客网 时间:2024/05/16 15:47
概述
关于okhttp口碑还是很好的,现在不管是Retrofit,Rxjava,Picasso等库都是okhttp的最佳搭档,所以还是很值得去学习一下。希望与大家共同进步,一同了解。
下面是github源码和官方地址
https://github.com/square/okhttp
http://square.github.io/okhttp/首先看一下他的调用
public class OkhttpUtil { private static String TAG = OkhttpUtil.class.getSimpleName(); private static OkHttpClient okHttpClient; private static OkhttpUtil okhttpUtil; private Request request; public static OkhttpUtil getInstance() { if(okHttpClient == null){ okHttpClient= new OkHttpClient(); } if(okhttpUtil == null){ okhttpUtil = new OkhttpUtil(); } return okhttpUtil; } public void asyncGet(String url, final ResuCallBack callBack){ request = new Request.Builder() .get() .url(url) .build(); Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { callBack.onFail(e.getMessage().toString()); Log.e(TAG,"r"+call.toString()); } @Override public void onResponse(Call call, Response response) throws IOException { callBack.onSuccess(response.body().string()); Log.e(TAG,"r"+response.body().toString()); Log.e(TAG,"r"+response.body().bytes()); } }); } public void asyncPost(String url,Map<String,String> map){ Request request = buildPostRequest(url, map); Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } }); } private Request buildPostRequest(String url, Map<String,String> params) { if (params == null) { params = new HashMap<>(); } FormBody.Builder formBody = new FormBody.Builder(); for (String key : params.keySet()) { formBody.add(key, params.get(key)); } RequestBody requestBody = formBody.build(); return new Request.Builder() .url(url) .post(requestBody) .build(); }}
从上面来看其实调用也简单,而且返回数据的格式是多种的可以是String,bytes等等
现在来看看调用过程发生了点什么。。。。。。。
首先看在OkHttpClient里面newCall()这个方法拿到的是Call的实现类RealCall的对象,从名字不难看出,这才是真正的干实事的家伙
/** * Prepares the {@code request} to be executed at some point in the future. */ @Override public Call newCall(Request request) { return new RealCall(this, request); }
RealCall
下面看看在RealCall里面,它到底是做什么东东的
首先看这里面三个内名内部类:
AsyncCall(线程):发起请求,吊起拦截器;ApplicationInterceptorChain(拦截器):这里主要是拿到HttpEngine对象,做一些实事;
HttpEngine(Http引擎) :请求的发起和返回数据的细节处理
(ps:下面代码会省略一部分)
final class RealCall implements Call { private final OkHttpClient client; Request originalRequest; HttpEngine engine; //同步请求 @Override public Response execute() throws IOException { synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } try { client.dispatcher().executed(this); Response result = getResponseWithInterceptorChain(false); if (result == null) throw new IOException("Canceled"); return result; } finally { client.dispatcher().finished(this); } } @Override public void enqueue(Callback responseCallback) { enqueue(responseCallback, false); } void enqueue(Callback responseCallback, boolean forWebSocket) { synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } //通过AsyncCall发起一个线程发起请求 client.dispatcher().enqueue(new AsyncCall(responseCallback, forWebSocket)); } @Override public void cancel() { canceled = true; if (engine != null) engine.cancel(); }... final class AsyncCall extends NamedRunnable { ... private AsyncCall(Callback responseCallback, boolean forWebSocket) { super("OkHttp %s", originalRequest.url().toString()); this.responseCallback = responseCallback; this.forWebSocket = forWebSocket; } .... @Override protected void execute() { boolean signalledCallback = false; try { Response response = getResponseWithInterceptorChain(forWebSocket); if (canceled) { 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! logger.log(Level.INFO, "Callback failure for " + toLoggableString(), e); } else { responseCallback.onFailure(RealCall.this, e); } } finally { client.dispatcher().finished(this); } } }... private Response getResponseWithInterceptorChain(boolean forWebSocket) throws IOException { Interceptor.Chain chain = new ApplicationInterceptorChain(0, originalRequest, forWebSocket); return chain.proceed(originalRequest); } class ApplicationInterceptorChain implements Interceptor.Chain { @Override public Response proceed(Request request) throws IOException { // If there's another interceptor in the chain, call that. if (index < client.interceptors().size()) { Interceptor.Chain chain = new ApplicationInterceptorChain(index + 1, request, forWebSocket); Interceptor interceptor = client.interceptors().get(index); Response interceptedResponse = interceptor.intercept(chain); if (interceptedResponse == null) { throw new NullPointerException("application interceptor " + interceptor + " returned null"); } return interceptedResponse; } // No more interceptors. Do HTTP. return getResponse(request, forWebSocket); } } Response getResponse(Request request, boolean forWebSocket) throws IOException { // Copy body metadata to the appropriate request headers. RequestBody body = request.body(); if (body != null) { Request.Builder requestBuilder = request.newBuilder(); MediaType contentType = body.contentType(); if (contentType != null) { requestBuilder.header("Content-Type", contentType.toString()); }... //进行发送请求和返回数据的细节处理 engine = new HttpEngine(client, request, false, false, forWebSocket, null, null, null); while (true) { try { engine.sendRequest(); engine.readResponse(); } catch (RequestException e) { } Response response = engine.getResponse(); Request followUp = engine.followUpRequest(); ..... } }
可以RealCall发起一个异步操作后通过ApplicationInterceptorChain拦截器转换到getResponse()方法里,这里拿到HttpEngine对象(Http引擎,处理请求发起和返回数据的读取的操作),然后进行网络请求的发送,返回数据的处理。下面我们来看一下HttpEngine.
HttpEngine
先看一下sendRequest(),在这里面我们发现他先是从Cache中是否能拿到数据
public void sendRequest() throws RequestException, RouteException, IOException { if (cacheStrategy != null) return; // Already sent. if (httpStream != null) throw new IllegalStateException(); Request request = networkRequest(userRequest); //查找用户缓存数据设置 InternalCache responseCache = Internal.instance.internalCache(client); //从缓存中读取之前相同请求得到的Response Response cacheCandidate = responseCache != null ? responseCache.get(request) : null; long now = System.currentTimeMillis(); cacheStrategy = new CacheStrategy.Factory(now, request, cacheCandidate).get(); networkRequest = cacheStrategy.networkRequest; cacheResponse = cacheStrategy.cacheResponse; if (responseCache != null) { responseCache.trackResponse(cacheStrategy); } if (cacheCandidate != null && cacheResponse == null) { closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it. } // If we're forbidden from using the network and the cache is insufficient, fail. if (networkRequest == null && cacheResponse == null) { userResponse = new Response.Builder() .request(userRequest) .priorResponse(stripBody(priorResponse)) .protocol(Protocol.HTTP_1_1) .code(504) .message("Unsatisfiable Request (only-if-cached)") .body(EMPTY_BODY) .build(); return; } // If we don't need the network, we're done //缓存中取数据 if (networkRequest == null) { userResponse = cacheResponse.newBuilder() .request(userRequest) .priorResponse(stripBody(priorResponse)) .cacheResponse(stripBody(cacheResponse)) .build(); userResponse = unzip(userResponse); return; } // We need the network to satisfy this request. Possibly for validating a conditional GET. //在这做请求的初始化的意思 boolean success = false; try { httpStream = connect(); httpStream.setHttpEngine(this); if (writeRequestHeadersEagerly()) { long contentLength = OkHeaders.contentLength(request); if (bufferRequestBody) { if (contentLength > Integer.MAX_VALUE) { throw new IllegalStateException("Use setFixedLengthStreamingMode() or " + "setChunkedStreamingMode() for requests larger than 2 GiB."); } if (contentLength != -1) { // Buffer a request body of a known length. httpStream.writeRequestHeaders(networkRequest); requestBodyOut = new RetryableSink((int) contentLength); } else { // Buffer a request body of an unknown length. Don't write request headers until the // entire body is ready; otherwise we can't set the Content-Length header correctly. requestBodyOut = new RetryableSink(); } } else { httpStream.writeRequestHeaders(networkRequest); requestBodyOut = httpStream.createRequestBody(networkRequest, contentLength); } } success = true; } finally { // If we're crashing on I/O or otherwise, don't leak the cache body. if (!success && cacheCandidate != null) { closeQuietly(cacheCandidate.body()); } } }
再来看看readResponse(),这个里面用到NetworkInterceptorChain拦截器发起请求
public void readResponse() throws IOException { if (userResponse != null) { return; // Already ready. } if (networkRequest == null && cacheResponse == null) { throw new IllegalStateException("call sendRequest() first!"); } if (networkRequest == null) { return; // No network response to read. } Response networkResponse; if (forWebSocket) { httpStream.writeRequestHeaders(networkRequest); networkResponse = readNetworkResponse(); } else if (!callerWritesRequestBody) { //发起网络请求 networkResponse = new NetworkInterceptorChain(0, networkRequest).proceed(networkRequest); } else { // Emit the request body's buffer so that everything is in requestBodyOut. if (bufferedRequestBody != null && bufferedRequestBody.buffer().size() > 0) { bufferedRequestBody.emit(); } // Emit the request headers if we haven't yet. We might have just learned the Content-Length. if (sentRequestMillis == -1) { if (OkHeaders.contentLength(networkRequest) == -1 && requestBodyOut instanceof RetryableSink) { long contentLength = ((RetryableSink) requestBodyOut).contentLength(); networkRequest = networkRequest.newBuilder() .header("Content-Length", Long.toString(contentLength)) .build(); } httpStream.writeRequestHeaders(networkRequest); } // Write the request body to the socket. if (requestBodyOut != null) { if (bufferedRequestBody != null) { // This also closes the wrapped requestBodyOut. bufferedRequestBody.close(); } else { requestBodyOut.close(); } if (requestBodyOut instanceof RetryableSink) { httpStream.writeRequestBody((RetryableSink) requestBodyOut); } } //拿到返回结果 networkResponse = readNetworkResponse(); } receiveHeaders(networkResponse.headers()); // If we have a cache response too, then we're doing a conditional get. if (cacheResponse != null) { if (validate(cacheResponse, networkResponse)) { userResponse = cacheResponse.newBuilder() .request(userRequest) .priorResponse(stripBody(priorResponse)) .headers(combine(cacheResponse.headers(), networkResponse.headers())) .cacheResponse(stripBody(cacheResponse)) .networkResponse(stripBody(networkResponse)) .build(); networkResponse.body().close(); releaseStreamAllocation(); // Update the cache after combining headers but before stripping the // Content-Encoding header (as performed by initContentStream()). InternalCache responseCache = Internal.instance.internalCache(client); responseCache.trackConditionalCacheHit(); responseCache.update(cacheResponse, stripBody(userResponse)); userResponse = unzip(userResponse); return; } else { closeQuietly(cacheResponse.body()); } } userResponse = networkResponse.newBuilder() .request(userRequest) .priorResponse(stripBody(priorResponse)) .cacheResponse(stripBody(cacheResponse)) .networkResponse(stripBody(networkResponse)) .build(); if (hasBody(userResponse)) { maybeCache(); userResponse = unzip(cacheWritingResponse(storeRequest, userResponse)); } }
上面可以看到他的请求是在engine.readResponse()中由拦截器完成
关于拦截器
拦截器的作用:先看看看看看….看Interceptor官方文档解释:
Observes, modifies, and potentially short-circuits requests going out and the corresponding responses coming back in. Typically interceptors add, remove, or transform headers on the request or response.大概意思呢就是:观察,修改以及可能短路的请求输出和响应请求的回来。通常情况下拦截器用来添加,移除或者转换请求或者回应的头部信息。
对于拦截器真的是okhttp的一大亮点,确实看着都很爽,用起来给我我们带来很大的方便
- Android Okhttp浅析
- 浅析okHttp
- 浅析OkHttp
- OkHttp源码浅析
- Android OKHTTP
- Android OkHttp
- Android OKHTTP
- Android OKHttp
- Android OkHttp
- Android OkHttp
- Android OkHttp
- Android OkHttp
- Android OKHttp
- android-OKHttp
- Android-----------OkHttp
- Android---OkHttp
- android+OKHTTP
- android+okhttp
- oracle sql case语句简单使用
- 面对对象三大特性—封装
- 常见正则表达式
- CSS:居中放置页面元素
- MYSQL中表的拷贝
- Android Okhttp浅析
- 38、39、40
- MVC使用Gantt Chart实现甘特图,管理事情进度(借鉴)
- SQLのT_SQL
- spring(基础10) 注解@Value详解
- SpringMVC学习笔记(二)——SpringMVC开发环境搭建
- js初识,博客初识
- 单例设计模式
- Linux操作系统的服务管理笔记