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的一大亮点,确实看着都很爽,用起来给我我们带来很大的方便

原创粉丝点击