美文网首页源码解析
OkHttp( 3.9.0-SNAPSHOT)源码解析

OkHttp( 3.9.0-SNAPSHOT)源码解析

作者: _warren | 来源:发表于2017-07-01 16:25 被阅读0次

    OkHttp源码的samples的简单使用的示例:

    public static void main(String... args) throws Exception{

    OkHttpClient client=new OkHttpClient();

    // Create request for remote resource.

    Request request=new Request.Builder()

    .url(ENDPOINT)

    .build();

    // Execute the request and retrieve the response.

    Response response=client.newCall(request).execute();

    // Deserialize HTTP response to concrete type.

    ResponseBody body=response.body();

    Listcontributors=CONTRIBUTORS_JSON_ADAPTER.fromJson(body.source());

    body.close();

    ......

    }

    静态常量

    OkHttpClient开始就定义了两个静态常量,这两个常量是与协议相关分别是DEFAULT_CONNECTION_SPECS和DEFAULT_PROTOCOLS。

    静态代码块

    接下来看OkHttpClient的static代码块主要就是创建了一个Internal的内部类对象。

    接口

    OkHttpClient实现了三个接口,分别是Cloneable,Call.Factory,WebSocket.Factory

    重点在Call.Factory接口上,Call该接口的实例就是我么去执行请求网络数据的对象,

    Call中的主要方法

    /** 返回该Call创建的Request请求对象 */

    Request request();

    /** 同步执行请求网络数据,返回服务端响应结果*/

    Response execute()throwsIOException;

    /** 异步执行请求网络数据的回调方法*/

    void enqueue(Callback responseCallback);

    /** 取消网络请求*/

    void cancel();

    /** 判断网络请求是否被执行了*/

    boolean isExecuted();

    /** 判断网络请求是否被取消了*/

    boolean isCanceled();

    /**clone该方法是Cloneable接口中的方法,意义在于创建一个相同的请求对象*/

    Call clone();

    /**Factory内部接口就是创建Call的工厂接口,该接口定义的方法newCall需要传入Request对象*/

    interface Factory{

    Call newCall(Request request);

    }

    成员变量

    最重要的就是OkHttpClient,该类的成员变量中6个成员变量进行重点说明的

    final Dispatcher dispatcher;

    final List interceptors;

    final List networkInterceptors;

    final EventListener.Factory eventListenerFactory;

    final @Nullable Cache cache; 

    final @Nullable InternalCache internalCache;

    1、同步请求过程解析

    Response response=client.newCall(request).execute(); 这句代码执行过程:

    (1)client.newCall(request)

    第一步:上面提到OkHttpClient的三个接口中有个Factory内部接口(创建Call的工厂接口),而Call对象有个实现类RealCall,其实newCall方法是RealCall执行自己的newRealCall方法创建了一个RealCall实例,该方法三个参数如下:

    *@param client OkHttpClient对象

    *@param originalRequest 之前传入的那个原始请求对象

    *@param forWebSocket 是否是WebSocket

    RealCall call=newRealCall(client,originalRequest,forWebSocket);

    第二步:上面提到OkHttpClient的6个成员变量中有个EventListener.Factory eventListenerFactory对象(也是个工厂接口,内部定义了一个create方法用于创建EventListener对象),上一步传入了OkHttpClient对象,该对象已经创建完了eventListenerFactory实例,所以拿到该实例传入call对象创建EventListener对象。

    抽象类EventListener中有一大堆的网络连接的监听方法

    call.eventListener=client.eventListenerFactory().create(call);

    最后返回当前的Call对象

    (2)call.execute()

    @Override

    publicResponse execute()throwsIOException{

        synchronized(this) {

        if(executed)throw newIllegalStateException("Already Executed");

         executed=true;

    }

       captureCallStackTrace();

     try{

           client.dispatcher().executed(this);

          Response result=getResponseWithInterceptorChain();

          if(result==null)throw newIOException("Canceled");

           returnresult;

          }finally{

           client.dispatcher().finished(this);

       }

    }

    2.1)call中的execute方法中的client.dispatcher().executed(this);

    由于execute是同步执行网络请求所以要用关键字synchronized,

    synchronized(this) {

        if(executed)throw newIllegalStateException("Already Executed");

       executed=true;

    }

    之后再执行captureCallStackTrace()方法,放入堆栈进行追踪捕捉。

    client.dispatcher()是获得上面OkHttpClient的成员变量Dispatcher dispatcher,注意啦Dispatcher中的方法基本都是同步,用的Synchronized修饰的方法。为了分析清楚这里插一段Dispatcher的说明。

    Dispatcher中维护着执行发送请求的线程池,所有的请求都是放在请求队列中的总共有三个队列readyAsyncCalls(准备的异步请求队列),runningAsyncCalls(正在在执行的异步请求还包括被中断的),runningSyncCalls(正在在执行的异步请求还包括被中断的)

    private final Deque<AsyncCall> readyAsyncCalls=newArrayDeque<>();

    private final Deque<AsyncCall> runningAsyncCalls=newArrayDeque<>();

    private final Deque<RealCall> runningSyncCalls=newArrayDeque<>();

    RealCall和AsyncCall的关系通过Dispatcher类的导入代码可以看出

    import okhttp3.RealCall.AsyncCall;   // AsyncCall其实就是RealCall的内部类

    具体实现如下:

    final class AsyncCall extends NamedRunnable{

    private final Callback responseCallback;

    // 构造时需要传入一个Callback接口,也就是返回给我们成功失败的回调方法

    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,newIOException("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{

           responseCallback.onFailure(RealCall.this,e);

       }

          }finally{

            client.dispatcher().finished(this);

          }

       }

    }

    dispatcher中erexecuted方法的具体实现

    //  加入同步执行队列

    synchronized void executed(RealCall call) {

      runningSyncCalls.add(call);

    }

    2.2)Response result=getResponseWithInterceptorChain();

    下面回过头去看RealCall的execute方法中client.dispatcher().executed(this);执行结束后的代码Response result=getResponseWithInterceptorChain();

    为了分析清楚这里插一段Interceptor的说明

    Response getResponseWithInterceptorChain()throwsIOException{

    //创建一个存放拦截器的集合,最后传入 newRealInterceptorChain对象中

       List<Intercepter>  interceptors=newArrayList<>();

    // client.interceptors() (自定义的拦截器, 在call api的前的拦截) - > //retryAndFollowUpInterceptor (实现请求重试)

       interceptors.addAll(client.interceptors());

    // 重定向拦截器

       interceptors.add(retryAndFollowUpInterceptor);

    // 桥接拦截器(处理header 、cookie 等)

       interceptors.add(newBridgeInterceptor(client.cookieJar()));

    // 缓存拦截器(处理 cache)

       interceptors.add(newCacheInterceptor(client.internalCache()));

    // 连接拦截器(负责建立连接)

       interceptors.add(newConnectInterceptor(client));

       if(!forWebSocket) {

    // 自定义网络拦截器(此时已建立连接)

         interceptors.addAll(client.networkInterceptors());

      }

    // 服务请求拦截器(发起请求、接收响应)

       interceptors.add(newCallServerInterceptor(forWebSocket));

    Interceptor.Chain chain = new RealInterceptorChain(interceptors,null,null,null,0,originalRequest,this,eventListener);   return chain.proceed(originalRequest);

    上面的RealInterceptorChain方法具体实现。在RealCall里的getResponseWithInterceptorChain方法里,创建了一个RealInterceptorChain对象,调用proceed(),在interceptor的intercept()方法里又调用proceed(),明显形成了一个递归,像链表一下一个一个递归传递并且做相应的拦截处理。

    RealInterceptorChain next=newRealInterceptorChain(interceptors,streamAllocation,httpCodec,

    connection,index+1,request,call,eventListener);

    Interceptor interceptor=interceptors.get(index);

    Response response=interceptor.intercept(next);

    最后一个拦截器返回处理的Response,也就是服务器端返回的结果,并且在代码中加了许多的判断如:this.httpCodec!=null 意思就是还没有拦截链执行完。interceptor必须执行一次proceed()方法,否则会抛异常。

    RealInterceptorChain + Interceptor实现了装饰器模式,实现了请求/响应的串式或流式处理。只不过内层装饰器不是外层装饰器的成员变量,而是接口方法中创建的临时变量。

    在ConnectInterceptor之后的拦截器必须满足:request的url要一致,interceptor必须执行一次proceed()。这样子做是为了保证递推的正常运作。而对与client.interceptors是在ConnectInterceptor之前的拦截器,可以不用必须执行一次proceed()。可以实现直接返回虚拟的response用于是测试等功能。

    这几个Interceptor的职责:

    RetryAndFollowUpInterceptor --->创建StreamAllocation对象,处理http的redirect,出错重试。对后续Interceptor的执行的影响:修改request及StreamAllocation。

    BridgeInterceptor-------------->补全缺失的一些http header。对后续Interceptor的执行的影响:修改request。

    CacheInterceptor-------------->处理http缓存。对后续Interceptor的执行的影响:若缓存中有所需请求的响应,则后续Interceptor不再执行。

    ConnectInterceptor------------>借助于前面分配的StreamAllocation对象建立与服务器之间的连接,并选定交互所用的协议是HTTP 1.1还是HTTP 2。对后续Interceptor的执行的影响:创建了httpStream和connection。

    CallServerInterceptor----------->处理IO,与服务器进行数据交换。对后续Interceptor的执行的影响:为Interceptor链中的最后一个Interceptor,没有后续Interceptor

    2.3client.dispatcher().finished(this); 

    dispatcher中finish方法的具体实现(注意第三个参数的差别)

    /** Used by {@codeCall #execute} to signal completion.同步方法 */

    void finished(RealCall call) {

        finished(runningSyncCalls,call,false);

    }

    /** Used by {@codeAsyncCall#run} to signal completion. 异步方法*/

    void  finished(AsyncCall call) {

        finished(runningAsyncCalls,call,true);

    }

    上面的finished(runningAsyncCalls,call,true);方法实现如下:

    private void finished(Dequecalls,T call,boolean promoteCalls) {

       int  runningCallsCount;

       Runnable idleCallback;

      synchronized(this) {

        if (!calls.remove(call) ) throw newAssertionError("Call wasn't in-flight!");

          if(promoteCalls)  promoteCalls(); // 异步Call数量多时需要维护队列,而不是立即执.行,所以要加入到runningAsyncCalls中

           runningCallsCount = runningCallsCount();

           idleCallback = this.idleCallback;

      }

      if(runningCallsCount==0&&idleCallback!=null) {

        idleCallback.run();

      }

    }

    上面promoteCalls方法的具体实现如下:

    private int maxRequests=64;

    private int maxRequestsPerHost=5;

    private void promoteCalls() {

        if(runningAsyncCalls.size()>=maxRequests) return;// 已经达到最大容器.

         if ( readyAsyncCalls.isEmpty() ) return; // 队列为空

            for(Iterator i=readyAsyncCalls.iterator();i.hasNext();) {  // 遍历取出

              AsyncCall call=i.next();  

     // 当正在执行的任务总数及相同host下的任务数小于最大值时,直接执行当前请求,而任务数超过限定时,将其加入等待队列。

              if ( runningCallsForHost(call) < maxRequestsPerHost ){ 

                 i.remove();

                runningAsyncCalls.add(call);

                executorService().execute(call);

              }

         }

        if ( runningAsyncCalls.size()>=maxRequests ) return;// Reached max capacity.

     }

    }

    还可以通setMaxRequests()设置同时允许执行的最大请求数,以及setMaxRequestsPerHost()设置相同host下最多运行的请求数。从源码中看出OkHttpClient用了许多的Budiler设计模式,几个重要的类Response、Request、OkHttpClient。

    2、异步请求过程解析

    RealCall的enqueue方法,其中遇到的大部分方法在同步请求中有分析就不赘述了。主要讲一下异步网络请求的流程

    @Override

    public voidenqueue(Callback responseCallback) {

      synchronized(this) {

          if(executed)throw newIllegalStateException("Already Executed");  

         executed=true;

     }

        captureCallStackTrace();

        client.dispatcher().enqueue(newAsyncCall(responseCallback));

    }

    上面client.dispatcher().enqueue(newAsyncCall(responseCallback));中Dispatcher的enqueue方法

    synchronized void enqueue(AsyncCall call) {

    // 如果正在执行异步请求的队列没有超过最大请求数量,并且有没有超过每个主机允许的最大访问量

    // 就将请求加入到正在执行异步请求的队列中,否则就加入到准备异步请求的队列中去

      if(runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost

         runningAsyncCalls.add(call); 

         executorService().execute(call);

       }else{

          readyAsyncCalls.add(call);

       }

    异步请求返回是通过接口回调的具体实现如下:

    final classAsyncCallextendsNamedRunnable{

    private finalCallback 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 voidexecute() {

       booleansignalledCallback=false;

    try{

        Response response=getResponseWithInterceptorChain();

        if (retryAndFollowUpInterceptor.isCanceled() ) {

           signalledCallback=true;

           responseCallback.onFailure(RealCall.this,newIOException("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{

              responseCallback.onFailure(RealCall.this,e);

           }

       }finally{

         client.dispatcher().finished(this);

       }

     }

    }

    相关文章

      网友评论

        本文标题:OkHttp( 3.9.0-SNAPSHOT)源码解析

        本文链接:https://www.haomeiwen.com/subject/qiywcxtx.html