OkHttp简单使用及源码分析

文章目录简单使用源码分析整体架构简介Interface——接口层Protocol——协议层Connection——连接层Cache——缓存层:管理本地缓存I/O——I/O层:实际数据读写实现Inteceptor——拦截器层:拦截网络访问,插入拦截逻辑Interface——接口层OkHttpClientRequestCallcall.execute()call.enqueue(callback)ca...
摘要由CSDN通过智能技术生成

简单使用

  1. OkHttp的github:https://github.com/square/okhttp

  2. 首先需要添加依赖

    implementation("com.squareup.okhttp3:okhttp:4.0.1")
    
  3. 添加网络权限

    <uses-permission android:name="android.permission.INTERNET" />
    
  4. 然后创建OkHttpClient对象

    OkHttpClient client = new OkHttpClient();
    //若要配置OkHttpClient,则应该通过OkHttpClient的Builder来创建OkHttpClient。
    OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(3, TimeUnit.SECONDS)
        .retryOnConnectionFailure(true)
        //...
        .build();
    
  5. 接着,创建Request对象

    // 上传单个文件
    RequestBody requestBody = RequestBody.create("", 								  		MediaType.parse("text/plain;charset=utf-8"));
    // 上传表单
    RequestBody requestBody1 = new MultipartBody.Builder()
        //上传表单必须要有这一句
        .setType(MultipartBody.FORM)
        .addFormDataPart("key", "value")
        .build();
    //FormBody是RequestBody的一个子类,只能用来上传表单内容都为字符串的表单
    FormBody formBody = new FormBody.Builder()
        .add("key", "value")
        .build();
    
    Request request = new Request.Builder()
        .url("https://www.google.com")
        //.get()
        //.method("post", requestBody)
        .post(formBody)
        .addHeader("content-type", "application/json")
        .build();
    
  6. 将Request对象封装为Call对象

    Call call = client.newCall(request);
    
  7. 决定同步还是异步执行

    // 同步执行
    call.execute();
    
    // 异步执行
    call.enqueue(new Callback() {
         
        @Override
        public void onFailure(Call call, IOException e) {
         
            Toast.makeText(context, "请求失败", Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void onResponse(Call call, final Response response) throws IOException {
         
            String res = response.body().string();
        }
    });
    

源码分析

整体架构

简介


如图所示OkHttp总体架构大概分为以下几层:

  • Interface——接口层:接收网络请求访问
  • Protocol层——协议层:处理协议逻辑
  • Connection——连接层:管理网络连接,发送新的请求,接受服务器访问
  • Cache——缓存层:管理本地缓存
  • I/O——I/O层:实际数据读写实现
  • Inteceptor——拦截器层:拦截网络请求,插入拦截逻辑
Interface——接口层

接口层用于接收用户的网络请求,发起实际的网络请求。具体见下面分析。

Protocol——协议层

协议层负责处理协议逻辑,OkHttp支持HTTP1/HTTP2/WebSocket三种协议。

Connection——连接层

该层负责网络连接。在连接层有一个连接池(RealConnectionPool),统一管理所有的Socket连接,当用户发起一个网络请求时,OkHttp会先从连接池中查找是否有符合要求的连接,若有则直接通过该连接发送网络请求,否则建立一个新连接发送请求。

RealConnection描述一个物理Socket连接,连接池中维护多个RealConnection对象。由于HTTP2支持多路复用,一个RealConnection支持多个网络访问请求,因此又引入了StreamAllocation来描述一个实际的网络请求开销,一个RealConnection对应一个或多个StreamAllocation,因此StreamAllocation可以看做是RealConnection的计数器,当RealConnection的引用计数变为0,且长时间没有被其他请求重新占用就将被释放。

Cache——缓存层:管理本地缓存

该层负责维护请求缓存,当用户的网络请求在本地已有符合要求的缓存时,OkHttp会直接从缓存中返回结果。见缓存拦截器的分析。

I/O——I/O层:实际数据读写实现

该层负责实际的数据读写。核心类:ExchangeCodec,此类只是一个接口。实现类是Http1ExchangeCodec和Http2ExchangeCodec

Inteceptor——拦截器层:拦截网络访问,插入拦截逻辑

拦截器层提供了一个类AOP接口,方便用户可以切入到各个层面对网络访问进行拦截并执行相关逻辑。具体下面介绍

Interface——接口层

接口层用于接收用户的网络请求,发起实际的网络请求。以下是几个类的介绍:

OkHttpClient:OkHttpClient是OkHttp框架的客户端,用户可以对其进行各种配置,发起网络请求都是通过OkHttpClient来完成的。每个OkHttpClient内部都维护了自己的任务队列,连接池,Cache,拦截器等,因此在一个项目工程中应该用单例模式。

Request:Request用来描述要发起请求。包括请求url、请求方法、请求头、请求体、缓存控制、是否是https请求。

Call:Call对象描述一个实际的网络请求,用户的每一个网络请求都是一个Call对象,一个Call对象只能被执行一次。Call实际是一个接口,实现类是RealCall类,用来描述同步请求。ReaCall类有一个内部类AsyncCall类,该类继承自Runnable接口,因此每一个Call就是一个线程,执行Call的过程就是执行器executeOn方法的过程。RealCall中保存了OkHttpClient、Request对象,以及标记了是否是WebSocket。

Dispatcher:该类是OkHttpClient的任务队列,其内部维护了一个线程池,当收到一个Call时,它负责在线程池中找到空闲的线程并执行其executeOn方法。

OkHttpClient
//不管如何,最后都创建了Builder对象。
//kotlin中的一个类可以有一个主构造函数以及一个或多个次构造函数。主构造函数是类头的一部分,跟在类名之后。
//若主构造函数没有任何注解或者可见性修饰符,可以省略internal关键字
//主构造函数不能包含任何代码,初始化代码可以放到init关键字作为前缀的初始化块中。主构造函数的参数可以在初始化块中使用。
//若有主构造函数,则每个次构造函数需要委托给主构造函数(直接或间接)
open class OkHttpClient internal constructor(
    builder: Builder
) : Cloneable, Call.Factory, WebSocket.Factory {
   
    //...
    constructor() : this(Builder())
    //...
    init {
   
        if (builder.sslSocketFactoryOrNull != null || connectionSpecs.none {
    it.isTls }) {
   
            this.sslSocketFactoryOrNull = builder.sslSocketFactoryOrNull
            this.certificateChainCleaner = builder.certificateChainCleaner
        } else {
   
            val trustManager = Platform.get().platformTrustManager()
            Platform.get().configureTrustManager(trustManager)
            this.sslSocketFactoryOrNull = newSslSocketFactory(trustManager)
            this.certificateChainCleaner = CertificateChainCleaner.get(trustManager)
        }

        if (sslSocketFactoryOrNull != null) {
   
            Platform.get().configureSslSocketFactory(sslSocketFactoryOrNull)
        }

        this.certificatePinner = builder.certificatePinner
        .withCertificateChainCleaner(certificateChainCleaner)

        check(null !in (interceptors as List<Interceptor?>)) {
   
            "Null interceptor: $interceptors"
        }
        check(null !in (networkInterceptors as List<Interceptor?>)) {
   
            "Null network interceptor: $networkInterceptors"
        }
    }
}
//Builder有两种创建方式:不带参,带OkHttpClient参数的构造方法。
class Builder constructor() {
   
    //kotlin中有四种可见性修饰符:private、protected、internal和public,默认为public。
    //public:随处可见
    //private:声明它的文件内可见
    //internal:模块(一个IDEA模块;一个Maven项目;一个Gradle源集;一次<kotlinc>Ant任务执行所编译的一套文件)内可见
    //protected:不适用于顶层声明。
    internal var dispatcher: Dispatcher = Dispatcher()//分发器
    internal var connectionPool: ConnectionPool = ConnectionPool()//连接池
    internal val interceptors: MutableList<Interceptor> = mutableListOf()//拦截器
    internal val networkInterceptors: MutableList<Interceptor> = mutableListOf()//网络拦截器
    internal var eventListenerFactory: EventListener.Factory = EventListener.NONE.asFactory()//监听器工厂
    internal var retryOnConnectionFailure = true//连接失败时是否重试
    internal var authenticator: Authenticator = Authenticator.NONE//本地身份验证
    internal var followRedirects = true//HTTP是否重定向
    internal var followSslRedirects = true//HTTPS是否重定向
    internal var cookieJar: CookieJar = CookieJar.NO_COOKIES//Cookie
    internal var cache: Cache? = null//缓存
    internal var dns: Dns = Dns.SYSTEM//域名解析
    internal var proxy: Proxy? = null//代理
    internal var proxySelector: ProxySelector = ProxySelector.getDefault() ?: NullProxySelector()//代理选择器
    internal var proxyAuthenticator: Authenticator = Authenticator.NONE//代理身份验证
    internal var socketFactory: SocketFactory = SocketFactory.getDefault()//socket工厂
    internal var sslSocketFactoryOrNull: SSLSocketFactory? = null//ssl socket工厂,用于HTTPS
    internal var connectionSpecs: List<ConnectionSpec> = DEFAULT_CONNECTION_SPECS//传输层版本和连接协议。
    internal var protocols: List<Protocol> = DEFAULT_PROTOCOLS//支持的协议
    internal var hostnameVerifier: HostnameVerifier = OkHostnameVerifier//用于确定主机名
    internal var certificatePinner: CertificatePinner = CertificatePinner.DEFAULT//证书链
    internal var certificateChainCleaner: CertificateChainCleaner? = null//证书确认
    internal var callTimeout = 0//调用超时时间
    internal var connectTimeout = 10_000//连接超时时间
    internal var readTimeout = 10_000//读取超时时间
    internal var writeTimeout = 10_000//写入超时时间
    internal var pingInterval = 0//长连接命令间隔

    internal constructor(okHttpClient: OkHttpClient) : this() {
   
        this.dispatcher = okHttpClient.dispatcher
        this.connectionPool = okHttpClient.connectionPool
        this.interceptors += okHttpClient.interceptors
        this.networkInterceptors += okHttpClient.networkInterceptors
        this.eventListenerFactory = okHttpClient.eventListenerFactory
        this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure
        this.authenticator = okHttpClient.authenticator
        this.followRedirects = okHttpClient.followRedirects
        this.followSslRedirects = okHttpClient.followSslRedirects
        this.cookieJar = okHttpClient.cookieJar
        this.cache = okHttpClient.cache
        this.dns = okHttpClient.dns
        this.proxy = okHttpClient.proxy
        this.proxySelector = okHttpClient.proxySelector
        this.proxyAuthenticator = okHttpClient.proxyAuthenticator
        this.socketFactory = okHttpClient.socketFactory
        this.sslSocketFactoryOrNull = okHttpClient.sslSocketFactoryOrNull
        this.connectionSpecs = okHttpClient.connectionSpecs
        this.protocols = okHttpClient.protocols
        this.hostnameVerifier = okHttpClient.hostnameVerifier
        this.certificatePinner = okHttpClient.certificatePinner
        this.certificateChainCleaner = okHttpClient.certificateChainCleaner
        this.callTimeout = okHttpClient.callTimeoutMillis
        this.connectTimeout = okHttpClient.connectTimeoutMillis
        this.readTimeout = okHttpClient.readTimeoutMillis
        this.writeTimeout = okHttpClient.writeTimeoutMillis
        this.pingInterval = okHttpClient.pingIntervalMillis
    }
}
Request
Request request  = new Request.Builder()
    .url("https://wwww.baidu.com")
    .get()
    .build();
//Request唯一的构造函数
class Request internal constructor(
  @get:JvmName("url") 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值