zoukankan      html  css  js  c++  java
  • Okhttp同步请求源码分析

    进阶android,OKhttp源码分析——同步请求的源码分析

    OKhttp是我们经常用到的框架,作为开发者们,我们不单单要学会灵活使用,还要知道他的源码是如何设计的。

    今天我们来分析一下OKhttp 同步请求的执行流程和源码分析

    so,老样子,我们先来一张图


     

    从上图可以看出,不管是同步请求还是异步请求,我们都需要创建一个OKhttpClient对象,用到的是build构造者模式,创建Request对象,然后再OKhttpClient的newCall方法和Request来封装我们的call对象。创建我们的实际请求的call对象,从上图可以看到,对于同步请求,我们调用的是excute方法,异步请求调用的是equeue方法。

    我们看一下做简单使用

    OkHttpClient okHttpClient = new  OkHttpClient.Builder()
                    .readTimeout(10, TimeUnit.SECONDS)
                    .build();
            Request request = new Request.Builder().url("https://blog.csdn.net/androidstarjack").build();
    
            Call call = okHttpClient.newCall(request);
            try {
                call.execute();//同步请求
                call.enqueue(new Callback() {//异步请求
                    @Override
                    public void onFailure(Call call, IOException e) {
    
                    }
    
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
    
                    }
                });
            } catch (IOException e) {
                e.printStackTrace();
            }
    
    

    我们先看一下okhttp的build


     

    首先我们通过源码可以看出,okhttp的创建时通过build方法来创建的,其中初始化了一些事情,比如创建一个dispatcher拦截器,和一个连接池,连接池只要是链接状态的保存以及复用。build是要是创建 okhttp是所需要的参数。

    在创建Request创建的时候也是用构造者模式进行创建的,源码如下:

      Builder(Request request) {
          this.url = request.url;
          this.method = request.method;
          this.body = request.body;
          this.tag = request.tag;
          this.headers = request.headers.newBuilder();
        }
    

    request的build构造里面初始化了一些请求的URL,请求方法哈请求头等请求报文的一些信息。

    Call对象 是通过他的父亲RealCall来完成的。


     

    Call对象持有了Okhttp 和Request两个对象,同时呢还创建了一个缓存拦截器RetryAndFollowUpInterceptor,用于所需要的重定向操作。

    通过调用okhttpClient的newCAll来完成CALL的新建,进行相应的操作

    紧接着调用execute方法来完成同步请求!

    @Override public Response execute() throws IOException {
        synchronized (this) {
          if (executed) throw new IllegalStateException("Already Executed");
          executed = true;
        }
        captureCallStackTrace();
        eventListener.callStart(this);
        try {
          client.dispatcher().executed(this);
          Response result = getResponseWithInterceptorChain();
          if (result == null) throw new IOException("Canceled");
          return result;
        } catch (IOException e) {
          eventListener.callFailed(this, e);
          throw e;
        } finally {
          client.dispatcher().finished(this);
        }
      }
    
    

    //布尔值executed表示一个okhttp请求只能运行执行一次,然后开启捕捉一些错误堆栈信息,点用一个eventListener监听方法,
    接卸来是调用分发器的executed方法。这才是重中之重。

    ...
     client.dispatcher().executed(this);
    ...
    
    

    client.dispatcher返回一个分发器。然后通过分发器来执行操作:


     

    在同步请求中,调用executed方法,很简单酒吧这个Call对象添加到队列当中。

    Dispatcher的作用主要是维持call请求发给他 的状态,同时维护了一个线程池,开启了网络请求。

    从源码中我们可以看到Dispatcher


     

    这几个请求队列代表着不同状态下的请求情况。

    紧接着通过拦截器链依次调用执行操作。
    最后还调用了Finish方法


     

    注意第三个参数,为false,这个方法的主要作用就是移除当前的请求,如果不能移除的话,返回异常,我们可以注意到,同步请求不需要调用promoteCalls,只有在异步请求的时候才会调用到,这个方法以后我们在讲。

    最后判断,正在将要执行的请求队列集合为0并且闲调用的回调不为null时,调用其run方法。此时,同步方法执行完成。


     

    如果对技术开发比较感兴趣,欢迎关注公众号:终端研发部。一起交流技术,进阶!

  • 相关阅读:
    [题解] [NOIP2008] 双栈排序——关系的冲突至图论解法
    [搬运] [贪心]NOIP2011 观光公交
    [总结] 最短路径数问题
    [持续更新]一些zyys的题的集合
    [教程]Ubuntu下完整配置自动壁纸切换
    在NOILINUX下的简易VIM配置
    [模板]ST表浅析
    21、Android--RecyclerView
    20、Android--GridView
    19、Android--ListView
  • 原文地址:https://www.cnblogs.com/gooder2-android/p/10342505.html
Copyright © 2011-2022 走看看