Okhttp3源码解析(2)-Request分析

作者: 秦子帅 | 来源:发表于2019-08-16 14:18 被阅读21次

    前言

    前面我们讲了
    Okhttp的基本用法
    Okhttp3源码解析(1)-OkHttpClient分析

    今天主要分析下Request源码!

    Request初始化

    当我们构建完OkHttpClient对象,需要构造Request对象,构造方式如下:

    1.Get请求
          final Request request=new Request.Builder()
                    .url("https://www.wanandroid.com/navi/json")
                    .get()
                    .build();
    
    
    2.POST请求

    拿POST提交表单请求,这时就需要声明一个RequestBody对象了

        RequestBody requestBody = new FormBody.Builder()
                    .add("username", "qinzishuai")
                    .add("password", "123456")
                    .build();
            Request request = new Request.Builder()
                    .url("https://www.wanandroid.com/user/login")
                    .post(requestBody)
                    .build();
    

    看到上面代码是不是很熟悉?和OkHttpClient很相似, 没错 Request 的构建也是Builder模式!


    我们点击Request源码进去,果然 其中有静态的Builder内部类:

    然后我们查一下Request在初始化时配置了哪些参数???

      public static class Builder {
        HttpUrl url;
        String method;
        Headers.Builder headers;
        RequestBody body;
    
    
        public Builder() {
          this.method = "GET";
          this.headers = new Headers.Builder();
        }
    
       //省略部分代码
        public Request build() {
          if (url == null) throw new IllegalStateException("url == null");
          return new Request(this);
        }
    }
    
    

    从代码看到了 如果没有声明,默认是Get请求 this.method = "GET" ,至于url等字段需要我们自己去配置:

    HttpUrl

    请求访问的url ,可以传String与URL 具体方法如下:

     public Builder url(String url) {
          if (url == null) throw new NullPointerException("url == null");
    
          // Silently replace web socket URLs with HTTP URLs.
          if (url.regionMatches(true, 0, "ws:", 0, 3)) {
            url = "http:" + url.substring(3);
          } else if (url.regionMatches(true, 0, "wss:", 0, 4)) {
            url = "https:" + url.substring(4);
          }
    
          return url(HttpUrl.get(url));
        }
    
    
        public Builder url(URL url) {
          if (url == null) throw new NullPointerException("url == null");
          return url(HttpUrl.get(url.toString()));
        }
    
    method

    请求类型 String method,支持多种请求类型

        public Builder get() {
          return method("GET", null);
        }
    
        public Builder head() {
          return method("HEAD", null);
        }
    
        public Builder post(RequestBody body) {
          return method("POST", body);
        }
    
        public Builder delete(@Nullable RequestBody body) {
          return method("DELETE", body);
        }
    
        public Builder delete() {
          return delete(Util.EMPTY_REQUEST);
        }
    
        public Builder put(RequestBody body) {
          return method("PUT", body);
        }
    
        public Builder patch(RequestBody body) {
          return method("PATCH", body);
        }
    
    Headers

    Headers.Builder Http消息的头字段
    前面看到了, 我们在初始化Request的时候 同时初始化了headers, this.headers = new Headers.Builder()

    可以通过 header addHeader removeHeader headers 方法做一些操作

       public Builder header(String name, String value) {
          headers.set(name, value);
          return this;
        }
    
        public Builder addHeader(String name, String value) {
          headers.add(name, value);
          return this;
        }
    
        public Builder removeHeader(String name) {
          headers.removeAll(name);
          return this;
        }
    
        public Builder headers(Headers headers) {
          this.headers = headers.newBuilder();
          return this;
        }
    
    
    body

    RequestBody类型,它是抽象类, 有些请求需要我们传入body实例 ,我们在通过源码来看一下:
    如果是GET请求,body对象传的是null
    Get与head方法不能传body对象 ,其他method是可以的

    如果是POST请求,就需要我们去设定了


    RequestBody解析

    首先我们看一下RequestBody如何初始化??拿提交表单举例:

        RequestBody requestBody = new FormBody.Builder()
                    .add("username", "qinzishuai")
                    .add("password", "000000")
                    .build();
    
    

    不出所料,也是Builder模式,而且RequestBody 是抽象类, FormBodyRequestBody的其中一种实现类 ,另一个实现类是MultipartBody
    RequestBody源码如下:

    public abstract class RequestBody {
      /** Returns the Content-Type header for this body. */
      public abstract @Nullable MediaType contentType();
    
      /**
       * Returns the number of bytes that will be written to {@code sink} in a call to {@link #writeTo},
       * or -1 if that count is unknown.
       */
      public long contentLength() throws IOException {
        return -1;
      }
    
      /** Writes the content of this request to {@code sink}. */
      public abstract void writeTo(BufferedSink sink) throws IOException;
    
      /**
       * Returns a new request body that transmits {@code content}. If {@code contentType} is non-null
       * and lacks a charset, this will use UTF-8.
       */
      public static RequestBody create(@Nullable MediaType contentType, String content) {
        Charset charset = Util.UTF_8;
        if (contentType != null) {
          charset = contentType.charset();
          if (charset == null) {
            charset = Util.UTF_8;
            contentType = MediaType.parse(contentType + "; charset=utf-8");
          }
        }
        byte[] bytes = content.getBytes(charset);
        return create(contentType, bytes);
      }
    
      /** Returns a new request body that transmits {@code content}. */
      public static RequestBody create(
          final @Nullable MediaType contentType, final ByteString content) {
        return new RequestBody() {
          @Override public @Nullable MediaType contentType() {
            return contentType;
          }
    
          @Override public long contentLength() throws IOException {
            return content.size();
          }
    
          @Override public void writeTo(BufferedSink sink) throws IOException {
            sink.write(content);
          }
        };
      }
    
      /** Returns a new request body that transmits {@code content}. */
      public static RequestBody create(final @Nullable MediaType contentType, final byte[] content) {
        return create(contentType, content, 0, content.length);
      }
    //省略部分代码...
    }
    

    核心方法有三个:

    • contentType()//数据类型
    • contentLength()//数据长度
    • writeTo(BufferedSink sink) //写操作

    今天就讲到这里,希望对大家有所帮助...

    大家可以关注我的微信公众号:「秦子帅」一个有质量、有态度的公众号!

    公众号

    相关文章

      网友评论

        本文标题:Okhttp3源码解析(2)-Request分析

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