### 前言
前面我们讲了
[Okhttp的基本用法](https://www.jianshu.com/p/8e404d9c160f)
[Okhttp3源码解析(1)-OkHttpClient分析](https://www.jianshu.com/p/bf1d01b79ce7)

今天主要分析下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模式!
![](https://img2018.cnblogs.com/blog/1312938/201908/1312938-20190823180241877-899976016.png)

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

![](https://img2018.cnblogs.com/blog/1312938/201908/1312938-20190823180242273-1916386988.png)

然后我们查一下**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是可以的**

![](https://img2018.cnblogs.com/blog/1312938/201908/1312938-20190823180242513-433063641.png)

如果是POST请求,就需要我们去设定了
![](https://img2018.cnblogs.com/blog/1312938/201908/1312938-20190823180242695-600270897.png)

### RequestBody解析
首先我们看一下RequestBody如何初始化??拿提交表单举例:
```
RequestBody requestBody = new FormBody.Builder()
.add("username", "qinzishuai")
.add("password", "000000")
.build();

```
不出所料,也是Builder模式,而且`RequestBody` 是抽象类, `FormBody`是`RequestBody`的其中一种实现类 ,另一个实现类是`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) //写操作

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

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

![公众号](https://img2018.cnblogs.com/blog/1312938/201908/1312938-20190823180242882-2108811045.jpg)

最新文章

  1. js数组的队栈操作
  2. JavaScript:关于事件处理程序何时可以直接访问元素的属性
  3. TextView里限制输入字数的方法
  4. Saltstack常用模块及API
  5. Servlet下
  6. Linux相关指令
  7. linux appear packet loss solution
  8. poj 3216 (最小路径覆盖)
  9. 数据传输对象(DTO)介绍及各类型实体比较
  10. centos 6.4 x64安装bugfree
  11. NancyFx 2.0的开源框架的使用-Caching
  12. 01背包java实现(入门到精通)
  13. 转---Python——numpy random类
  14. python -- 题目不看别人的自己写然后比较
  15. xlsx 库 知识点
  16. Python入门2(Python与C语言语法的不同、Notepad++运行Python代码)
  17. Install Identity management Database
  18. Android-bindService本地服务-音乐播放(后台播放)-下
  19. UEditor图片焦点错位,火狐document.body.scrollTop不管用的问题
  20. Google-优秀移动站点设计10招

热门文章

  1. [leetcode] 7. Reverse Integer (easy)
  2. 在工作中常用的Linux命令
  3. C# Winform程序如何使用ClickOnce发布并自动升级(图解)
  4. linux初学者-进程篇
  5. JasperReport报表
  6. spring读取xml配置文件(二)
  7. 一文掌握 Spring Boot Profiles
  8. 虚IP解决程序连只读服务器故障漂移
  9. C#中属性的解析
  10. 2. 源码分析---SOFARPC客户端服务引用