现在得android网络请求框架中使用得最多得还是okhttp,okhttp得拦截机制很巧妙,所以就看下是如何设计得。

一般得使用例子如下。

OkHttpClient okHttpClient = new OkHttpClient.Builder()        .build();Request request = new Request.Builder()        .url(url)        .build();okHttpClient.newCall(request).enqueue(new Callback() {    @Override    public void onFailure(Call call, IOException e) {    }    @Override    public void onResponse(Call call, Response response) throws IOException {    }});

构建一个OkHttpClient客户端和一个请求Request,然后调用newCall发送请去。先看下一张okhttp整个网络架构图。

                                (https://raw.githubusercontent.com/sucese/android-open-framework-                          analysis/master/art/okhttp/request_and_response_structure.png)

网络配置层:利用Builder模式配置各种参数,例如:超时时间、拦截器等,这些参数都会由Okhttp分发给各个需要的子系统。

重定向层:负责重定向。

Header拼接层:负责把用户构造的请求转换为发送给服务器的请求,把服务器返回的响应转换为对用户友好的响应。

HTTP缓存层:负责读取缓存以及更新缓存。

连接层:连接层是一个比较复杂的层级,它实现了网络协议、内部的拦截器、安全性认证,连接与连接池等功能,但这一层还没有发起真正的连接,它只是做了连接器一些参数的处理。

数据响应层:负责从服务器读取响应的数据。

Okhttp的整个请求与响应的流程就是Dispatcher不断从Request Queue里取出请求(Call),根据是否已经存存缓存,从内存缓存或者服务器获取请求的数据,请求分为同步和异步两种,同步请求通过 调用Call.exectute()方法直接返回当前请求的Response,异步请求调用Call.enqueue()方法将请求(AsyncCall)添加到请求队列中去,并通过回调(Callback)获取服务器返回的结果。

整个请求和响应得过程中,设计了一层一层得拦截器,每个拦截器对应相应得功能,简化了设计逻辑,提升了框架得扩展性。接着看下,Dispatcher是如何请求得。

先看下整个拦截流程。

(https://raw.githubusercontent.com/sucese/android-open-framework-analysis/master/art/okhttp/request_and_response_sequence.png)

发起请求在newCall中。

  /**   * Prepares the {@code request} to be executed at some point in the future.   */  @Override public Call newCall(Request request) {    return RealCall.newRealCall(this, request, false /* for web socket */);  }

真正请求得是RealCall得newRealCall,RealCall是继承Call这个接口得。

public interface Call extends Cloneable {  //当前请求  Request request();  //同步请求方法  Response execute() throws IOException;  //异步请求方法  void enqueue(Callback responseCallback);  //取消请求  void cancel();  //是否执行  boolean isExecuted();  //是否取消  boolean isCanceled();    Call clone();  interface Factory {    Call newCall(Request request);  }}

RealCall的构造方法

  private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {    this.client = client;    this.originalRequest = originalRequest;    this.forWebSocket = forWebSocket;    this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);  }

RealCall实现了Call接口,分装请求,赋值外部传入的OkHttpClient、Request与forWebSocket,并 创建了重试与重定向拦截器RetryAndFollowUpInterceptor。

请求分为同步请求和异步请求。

异步请求。

final class RealCall implements Call {          @Override public void enqueue(Callback responseCallback) {        synchronized (this) {          if (executed) throw new IllegalStateException("Already Executed");          executed = true;        }        captureCallStackTrace();        client.dispatcher().enqueue(new AsyncCall(responseCallback));      }}

同步请求

final class RealCall implements Call {    @Override public Response execute() throws IOException {      synchronized (this) {        if (executed) throw new IllegalStateException("Already Executed");        executed = true;      }      captureCallStackTrace();      try {        client.dispatcher().executed(this);        Response result = getResponseWithInterceptorChain();        if (result == null) throw new IOException("Canceled");        return result;      } finally {        client.dispatcher().finished(this);      }    }}

从上面可知,无论是同步还是异步请求,都是交给Dispatcher处理。AsyncCall本质上是一个Runnable。

  final class AsyncCall extends NamedRunnable {    private final Callback responseCallback;    AsyncCall(Callback responseCallback) {      super("OkHttp %s", redactedUrl());      this.responseCallback = responseCallback;    }    String host() {      return originalRequest.url().host();    }    Request request() {      return originalRequest;    }    RealCall get() {      return RealCall.this;    }    @Override protected void execute() {      boolean signalledCallback = false;      try {        Response response = getResponseWithInterceptorChain();        if (retryAndFollowUpInterceptor.isCanceled()) {          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!          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);        } else {          eventListener.callFailed(RealCall.this, e);          responseCallback.onFailure(RealCall.this, e);        }      } finally {        client.dispatcher().finished(this);      }    }  }

从代码可以看到无论是同步还是异步,最终都是通过getResponseWithInterceptorChain()获取Response。

请求和响应流程完了,接着看下拦截调度是如何实现得。

 Response getResponseWithInterceptorChain() throws IOException {    // Build a full stack of interceptors.    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, this, eventListener, client.connectTimeoutMillis(),        client.readTimeoutMillis(), client.writeTimeoutMillis());    return chain.proceed(originalRequest);  }}

可以看到我们得拦截器是在这里添加得,Interceptor将网络请求、缓存、透明压缩等功能统一了起来,它的实现采用责任链模式,各司其职, 每个功能都是一个Interceptor,上一级处理完成以后传递给下一级,它们最后连接成了一个Interceptor.Chain。位置决定功能,位置靠前,先执行,所以我们自定义得拦截器是最先执行得。从发起到服务器返回数据得流程是相反得。

public interface Interceptor {  Response intercept(Chain chain) throws IOException;  interface Chain {    //发起得请求    Request request();        //返回的请求    Response proceed(Request request) throws IOException;    /**     * Returns the connection the request will be executed on. This is only available in the chains     * of network interceptors; for application interceptors this is always null.     */    @Nullable Connection connection();    Call call();    //连接超时得时间    int connectTimeoutMillis();    //设置连接超时    Chain withConnectTimeout(int timeout, TimeUnit unit);    //读取超时得时间    int readTimeoutMillis();   //设置读取超时    Chain withReadTimeout(int timeout, TimeUnit unit);    //写超时    int writeTimeoutMillis();    //设置写超时    Chain withWriteTimeout(int timeout, TimeUnit unit);  }}

Okhttp内置的拦截器如下所示:

  • RetryAndFollowUpInterceptor:负责失败重试以及重定向。
  • BridgeInterceptor:负责把用户构造的请求转换为发送给服务器的请求,把服务器返回的响应转换为对用户友好的响应。
  • CacheInterceptor:负责读取缓存以及更新缓存。
  • ConnectInterceptor:负责与服务器建立连接。
  • CallServerInterceptor:负责从服务器读取响应的数据。

Request是按照interpretor的顺序正向处理,而Response是逆向处理的。这参考了OSI七层模型的原理。上面我们也提到过。CallServerInterceptor相当于最底层的物理层, 请求从上到逐层包装下发,响应从下到上再逐层包装返回。

interceptor的执行顺序:RetryAndFollowUpInterceptor -> BridgeInterceptor -> CacheInterceptor -> ConnectInterceptor -> CallServerInterceptor。

response的拦截的执行顺序是:CallServerInterceptor ->ConnectInterceptor ->CacheInterceptor -> BridgeInterceptor ->

RetryAndFollowUpInterceptor 。

总结:

okhtto的拦截模式像OSI七层模型的原理,按照顺序拦截,理解起来非常的清晰,链路设计通俗易懂。

 

更多相关文章

  1. Android(安卓)的OkHttp(发送网络请求)
  2. Android(安卓)Studio第十九期 - Glin架构
  3. android使用okhttp网络请求失败:Expected ':status' header not p
  4. Android(安卓)Webview 基于chromedriver 查看具体页面pagesource
  5. 解决android http请求带中文参数会乱码(url编码)
  6. Android(安卓)在部分华为手机上出现乱码的问题
  7. Android(安卓)Studio上报错java.net.UnknownServiceException: C
  8. android 网络编程 HttpGet类和HttpPost类使用详解
  9. Okhttp封装

随机推荐

  1. Android五大存储之SharedPreference
  2. Android与js的交互方式
  3. Android中EventBus3.0的使用
  4. android 在 ubuntu 环境下真机调试
  5. Android新组件应用
  6. android 文本框部分文字的点击事件
  7. Android TextView 不刷新解决办法
  8. 在Visual Studio 2013/2015上使用C#开发A
  9. android实战项目二实现画板效果
  10. 在Eclipse IDE下实现下滑隐藏ToolBar