截图再上传实在麻烦,就简单把代码复制过来....
其实我什么也没说,我只是代码的搬运工.....
第一篇的时候描述了下怎么获取所有请求头,这篇简单介绍下okhttp添加系统请求header的实现过程,首先看下面代码:
private final OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("http://www.2cto.com/kf/201604/497726.html") .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
这段代码可以发起一个网络请求(注意放在子线程中执行)。
然后进入OkHttpClient.newCall(Request request)方法查看,代码如下:
OkHttpClient.java
@Override
public Call newCall(Request request) { return new RealCall(this, request); }
这里我们会看到newCall(Request request) 传入了一个Request请求,并返回了一个实例化的RealCall对象,
继续进入RealCall类进行查看会发现RealCall类实现了Call接口。
继续看最上面执行请求的代码,在返回RealCall的实例后进行了execute()方法的调用。继续进入RealCall类查看execute()方法,代码如下:
RealCall.java
@Override
public Response execute() throws IOException { synchronized(this) { if(this.executed) { throw new IllegalStateException("Already Executed"); } this.executed = true; } Response var2; try { this.client.dispatcher().executed(this); Response result = this.getResponseWithInterceptorChain(); if(result == null) { throw new IOException("Canceled"); } var2 = result; } finally { this.client.dispatcher().finished(this); } return var2; }
注意标红的代码,继续进行查看getResponseWithInterceptorChain()方法:
RealCall.java
private Response getResponseWithInterceptorChain() throws IOException { ArrayList interceptors = new ArrayList(); interceptors.addAll(this.client.interceptors()); interceptors.add(this.retryAndFollowUpInterceptor); interceptors.add(new BridgeInterceptor(this.client.cookieJar())); interceptors.add(new CacheInterceptor(this.client.internalCache())); interceptors.add(new ConnectInterceptor(this.client)); if(!this.retryAndFollowUpInterceptor.isForWebSocket()) { interceptors.addAll(this.client.networkInterceptors()); } interceptors.add(new CallServerInterceptor(this.retryAndFollowUpInterceptor.isForWebSocket())); RealInterceptorChain chain = new RealInterceptorChain(interceptors, (StreamAllocation)null, (HttpStream)null, (Connection)null, 0, this.originalRequest); return chain.proceed(this.originalRequest); }
上面的代码可以知道这里添加了一堆拦截器,OkHttp里面的拦截器是一个强大的工具,可以做到对网络请求和响应的随意修改,
下面继续查看标红的代码BridgeInterceptor类:
BridgeInterceptor.java
@Override
public Response intercept(Chain chain) throws IOException { Request userRequest = chain.request(); Builder requestBuilder = userRequest.newBuilder(); RequestBody body = userRequest.body(); if(body != null) { MediaType transparentGzip = body.contentType(); if(transparentGzip != null) { requestBuilder.header("Content-Type", transparentGzip.toString()); } long cookies = body.contentLength(); if(cookies != -1L) { requestBuilder.header("Content-Length", Long.toString(cookies)); requestBuilder.removeHeader("Transfer-Encoding"); } else { requestBuilder.header("Transfer-Encoding", "chunked"); requestBuilder.removeHeader("Content-Length"); } } if(userRequest.header("Host") == null) { requestBuilder.header("Host", Util.hostHeader(userRequest.url(), false)); } if(userRequest.header("Connection") == null) { requestBuilder.header("Connection", "Keep-Alive"); } boolean transparentGzip1 = false; if(userRequest.header("Accept-Encoding") == null) { transparentGzip1 = true; requestBuilder.header("Accept-Encoding", "gzip"); } List cookies1 = this.cookieJar.loadForRequest(userRequest.url()); if(!cookies1.isEmpty()) { requestBuilder.header("Cookie", this.cookieHeader(cookies1)); } if(userRequest.header("User-Agent") == null) { requestBuilder.header("User-Agent", Version.userAgent()); } Response networkResponse = chain.proceed(requestBuilder.build()); HttpHeaders.receiveHeaders(this.cookieJar, userRequest.url(), networkResponse.headers()); okhttp3.Response.Builder responseBuilder = networkResponse.newBuilder().request(userRequest); if(transparentGzip1 && "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))); } return responseBuilder.build(); }
BridgeInterceptor类实现了Interceptor接口的intercept(Chain chain)方法。
当进行网络拦截的时候会执行intercept(Chain chain)里面的代码,而这里面把设置了一些系统Header(关于OkHttp如何实现拦截过程不在本文讲述范围)。
继续回顾RealCall类中的execute()方法。这是一个同步的方法,使用的时候需要开启一个子线程进行网络请求,除此之外还有一个异步的方法enqueue(Callback responseCallback)不需要开启子线程当网络访问有结果是会调用Callback 的回掉方法。下面我们看下RealCall类中时如何实现这个方法的,代码如下:
@Override
public void enqueue(Callback responseCallback) { synchronized(this) { if(this.executed) { throw new IllegalStateException("Already Executed"); } this.executed = true; } this.client.dispatcher().enqueue(new RealCall.AsyncCall(responseCallback)); }
继续查看RealCall的内部类AsyncCall的实现:
final class AsyncCall extends NamedRunnable { private final Callback responseCallback; private AsyncCall(Callback responseCallback) { super("OkHttp %s", new Object[]{RealCall.this.redactedUrl().toString()}); this.responseCallback = responseCallback; } String host() { return RealCall.this.originalRequest.url().host(); } Request request() { return RealCall.this.originalRequest; } RealCall get() { return RealCall.this; } @Override protected void execute() { boolean signalledCallback = false; try { Response e = RealCall.this.getResponseWithInterceptorChain(); if(RealCall.this.retryAndFollowUpInterceptor.isCanceled()) { signalledCallback = true; this.responseCallback.onFailure(RealCall.this, new IOException("Canceled")); } else { signalledCallback = true; this.responseCallback.onResponse(RealCall.this, e); } } catch (IOException var6) { if(signalledCallback) { Platform.get().log(4, "Callback failure for " + RealCall.this.toLoggableString(), var6); } else { this.responseCallback.onFailure(RealCall.this, var6); } } finally { RealCall.this.client.dispatcher().finished(this); } } }
看到标红的代码可以知道,这里添加了同样的拦截器BridgeInterceptor类。而这些内容是重写的execute()方法里面,我们看下父类NamedRunnable的实现过程:
public abstract class NamedRunnable implements Runnable { protected final String name; public NamedRunnable(String format, Object... args) { this.name = Util.format(format, args); } @Override public final void run() { String oldName = Thread.currentThread().getName(); Thread.currentThread().setName(this.name); try { this.execute(); } finally { Thread.currentThread().setName(oldName); } } protected abstract void execute(); }
由此可以知道NamedRunnable抽象类时实现的Runnable的接口,并定义了一个未实现的方法execute()。而这个方法是在run()方法里面进行调用的。
嗯,整体大概就是这个样子的。
这里没有细说execute()方法和enqueue(Callback responseCallback)方法的区别,刚兴趣的话可以百度下。