OkHttp之Request请求

QuibblerQuibbler 2021-03-13 约 9 分钟 2042 次阅读

OkHttp之Request请求

了解了OkHttp的基本用法,不急着分析OkHttp网络请求流程。先熟悉一遍源码,了解请求相关的几个类:请求Request、请求体RequestBody以及请求头Headers。

阅读源码,一方面搞懂内部实现,遇到坑可以知道在哪。另一方面,吸取代码设计经验,设计模式不是纸上谈兵。

1、Request

先看Request源码,熟悉Request请求的设计。


1.1、请求核心成员

Request类中封装了和请求相关的成员:请求地址url、请求方法method、请求头headers、请求体body。

/**
      * 一个HTTP请求。 如果此类的实例[body]为null或本身immutable,则它是immutable。
      */
    class Request internal constructor(
        val url: HttpUrl,
	val method: String,
	val headers: Headers,
	val body: RequestBody?,
	...
    ){
	 private var lazyCacheControl: CacheControl? = null
	 val cacheControl: CacheControl
	 ...
    }

OkHttp用Kotlin重新实现了一遍,原先内部成员对应的getter方法已经不可用,直接访问上面定义的成员。

@Deprecated
    fun url(): HttpUrl = url
    
    @Deprecated
    fun method(): String = method
    
    @Deprecated
    fun headers(): Headers = headers
    
    @Deprecated
    fun body(): RequestBody? = body
    
    @Deprecated
    fun cacheControl(): CacheControl = cacheControl

1.2、主要方法

Request还对外提供了一些操作内部成员的方法,这是日常开发中常规的实现。

fun header(name: String): String? = headers[name]
    fun headers(name: String): List<String> = headers.values(name)
    ...

2、内部类Builder

Request的构造方法被修饰为internal,开发者应使用内部的Builder构造者来构造Request实例。

2.1、成员

        Request.Builder类内部也定义了和Request一样的成员:url、method、headers、body。

internal var url: HttpUrl? = null
    internal var method: String
    internal var headers: Headers.Builder
    internal var body: RequestBody? = null

2.2、构造Builder

Request.Builder有两个构造函数:一个无参默认构造函数,默认请求方法是GET。

constructor() {
      this.method = "GET"
      this.headers = Headers.Builder()
    }

另一个是以Request作为参数,相当于从另一个请求复制出一个请求。

internal constructor(request: Request) {
      this.url = request.url
      this.method = request.method
      this.body = request.body
      this.tags = if (request.tags.isEmpty()) {
        mutableMapOf()
      } else {
        request.tags.toMutableMap()
      }
      this.headers = request.headers.newBuilder()
    }

2.3、设置网络请求url

Builder设置网络请求的地址url,参数可以是String、也可以是URL或者HttpUrl。

open fun url(url: HttpUrl): Builder = apply {
      this.url = url
    }

    open fun url(url: String): Builder {
      // Silently replace web socket URLs with HTTP URLs.
      val finalUrl: String = when {
        url.startsWith("ws:", ignoreCase = true) -> {
          "http:${url.substring(3)}"
        }
        url.startsWith("wss:", ignoreCase = true) -> {
          "https:${url.substring(4)}"
        }
        else -> url
      }
      return url(finalUrl.toHttpUrl())
    }

    open fun url(url: URL) = url(url.toString().toHttpUrl())

2.4、设置网络请求方法

通过Builder,开发者可以设置网络请求的方法,内部也提供了HTTP常见几种方法:get()、head()、post()、delete()、put()等,开发者也可以调用method()自行设置方法。关于HTTP的请求方法在RESTful 统一接口一文中有提到。

//注意GET和HEAD是不需要RequestBody的。
    open fun get() = method("GET", null)
    open fun head() = method("HEAD", null)
    
    //这些方法需要RequestBody
    open fun post(body: RequestBody) = method("POST", body)
    open fun delete(body: RequestBody? = EMPTY_REQUEST) = method("DELETE", body)
    open fun put(body: RequestBody) = method("PUT", body)
    open fun patch(body: RequestBody) = method("PATCH", body)
    
    open fun method(method: String, body: RequestBody?): Builder = apply {
      ...
      this.method = method
      this.body = body
    }

2.5、build()请求实例

一切设置好之后,调用builder()构造Request实例,将内部的成员传入Request内部internal构造方法中。

open fun build(): Request {
      return Request(
          checkNotNull(url) { "url == null" },
          method,
          headers.build(),
          body,
          tags.toImmutableMap()
      )
    }

Request内部封装了body和headers,接下来继续看请求体RequestBody以及请求头Headers的源码,了解它们的内部实现。传送门:OkHttp之RequestBody请求体。

相关推荐

Airbnb开源项目
精选开源

Airbnb开源项目

Airbnb Engineering & Data ScienceAirflow Use Apache Airflow (incubating) to author workflows as directed acyclic graphs (DAGs) of tasks12,263Airpal Web UI for PrestoDB2,502Aerosolve A machine learning

2.3k
WilliamChart:轻量美观的 Android 图表库实战
精选开源

WilliamChart:轻量美观的 Android 图表库实战

WilliamChart:轻量美观的 Android 图表库实战数据可视化是运动、健康、金融、统计类 App 的刚需。MPAndroidChart 功能最全但偏重复杂,WilliamChart 走的则是"轻量 + 美观 + Kotlin 原生"路线——v3 用 Kotlin 完全重写,API 极简,一行 chart.animate(dataSet) 就能把数据画成带动画的折线/柱状/环形图,开箱即

175
sherpa解析:开源语音技术全家桶
精选开源

sherpa解析:开源语音技术全家桶

想在手机、树莓派甚至 RISC-V 开发板上离线跑语音识别,五年前还是个需要啃 Kaldi 源码的硬核课题。k2-fsa 组织的 sherpa 把这件事变成了"下载预训练模型、装个包、跑示例"的三步操作。这个以 Apache-2.0 协议开源的项目自我定位是"新一代 Kaldi 的语音转文本框架",它专注端到端模型的推理部署:transducer 与 CTC 两类架构,C++ 与 Python 双…

44