重识OkHttp——更深入了解如何使用

 我来答
会哭的礼物17
2022-07-04 · TA获得超过1.2万个赞
知道大有可为答主
回答量:7167
采纳率:100%
帮助的人:45.9万
展开全部

OkHttp作为square公司出品的一个网络请求框架,应该算是目前Android端最火爆的网络框架了。我公司目前的项目中采用的都是Rxjava结合Retrofit进行网络请求的处理,对于底层真正实现网络请求的OkHttp关注的不是很多。最近探究了一下OkHttp的源码,对OkHttp的使用有了一些新的认识,在此做一下总结。

OkHttp作为当前Android端最火热的网络请求框架,必然有很多的优点。

对于客户端来讲,我们关注的就是把正确的请求发送到服务端并拿到结果来进行处理。在OkHttp中,我认为可以分为3个部分:

OkHttp中通过建造者模式来构建OkHttpClient、Request和Response。对于客户端来讲,我们不需要过多关注Response是如何构建的,因为这个是OkHttp对响应结果进行了封装处理。我们只关注请求Request和客户端OkHttpClient如何构建即可。

Request采用建造者模式来配置url,请求方法method、header、tag和cacheControl。

OkHttp采用POST方法向服务器发送一个请求体,在OkHttp中这个请求体是RequestBody。这个请求体可以是:

RequestBody有几个静态方法用于创建不同类型的请求体:

最终都是相当于重写了RequestBody的两个抽象方法来写入流,如果传递流类型的参数,只要重写这两个抽象方法即可。

例如,我们提交一个String:

提交File:

提交流:

对于提交表单和分块请求,OkHttp提供了两个RequestBody的子类, FormBody MultipartBody

FormBody也是采用建造者模式, 这个很简单,添加key-value形式的键值对即可。
添加键值对有两个方法:

例如:

MultipartBody也是采用建造者模式,MultipartBody.Builder可以构建兼容Html文件上传表单的复杂请求体。每一部分的多块请求体都是它自身的请求体,并且可以定义它自己的请求头。如果存在的话,这些请求头用来描述这部分的请求体。例如Content-Disposition、Content-Length 和 Content-Type如果可用就会被自动添加到头。

MIME类型有:

有几个主要的方法:

例如提交一个图片文件:

OkHttpClient采用建造者模式,通过Builder可以配置连接超时时间、读写时间,是否缓存、是否重连,还可以设置各种拦截器interceptor等。
建议在一个App中,OkHttpClient保持一个实例。一个OkHttpClient支持一定数量的并发,请求同一个主机最大并发是5,所有的并发最大是64。这个与OkHttp中的调度器Dispatcher有关,可以设置并发数。本文不对Dispatcher进行讨论。

一个例子:

OkHttpClient支持单独配置,例如原来设置不同的请求时间,可以通过OkHttpClient的newBuilder()方法来重新构造一个OkHttpClient。例如:

上面已经讲了如何创建Request和OkHttpClient,剩下的就是发送请求并得到服务器的响应了。OkHttp发送请求可分为同步和异步。OkHttpClient首先通过Request构建一个Call,通过这个Call去执行同步或者异步请求。

同步方式,调用Call的execute()方法,返回Response,会阻塞当前线程:

异步方式,调用Call的enqueue(CallBack callBack)方法,会在另一个线程中返回结果。

为了缓存响应,需要一个可读写并且设置大小Size的缓存目录。缓存目录需要私有,其它不信任的应用不能访问这个文件。
如果同时有多个缓存访问同一个缓存目录会报错。所以最好只在App中初始化一次OkHttpClient,给这个实例配置缓存,在整个App生命周期内都用这一个缓存。否则几个缓存会相互影响,导致缓存出错,引起程序崩溃。
响应缓存采用Http头来配置,你可以添加这样的请求头 Cache-Control: max-stale=3600 max-age 指的是客户端可以接收生存期不大于指定时间(以 为单位)的响应。
为了防止响应使用缓存,可以用 CacheControl.FORCE_NETWORK 。为了防止使用网络,采用 CacheControl.FORCE_CACHE

调用Call.cancel()方法可以立即取消一个网络请求。如果当前线程正在写request或者读response会报IO异常。如果不再需要网络请求,采用这种方法是比较方便的。例如在App中返回了上一页。无论是同步还是异步的请求都可以被取消。

可以通过Response的code来判断请求是否成功,如果服务器返回的有数据,可以通过Response的body得到一个ResponseBody读取。
如果采用ResponseBody的string()方法会一次性把数据读取到内存中,如果数据超过1MB可能会报内存溢出,所以对于超过1MB的数据,建议采用流的方式去读取,如ResponseBody的byteStream()方法。

需要说明的是:

OkHttp中的很多类都用到了建造者模式,可以根据需要灵活配置。采用建造者模式的有:

如果单独使用OkHttp进行网络请求,通常需要开发者自己再封装一下,如果不想重复造轮子,Github上面的有一些优秀开源库可以拿来使用(本文只列出star较多的几个):

OkHttp官方Wiki文档

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
Storm代理
2023-07-25 广告
StormProxies是一家可靠的代理服务提供商,提供原生IP(住宅原生IP)和高匿名代理服务。以下是关于StormProxies的原生IP服务的一些信息:1. 住宅原生IP:StormProxies提供的住宅原生IP是指从真实的家庭或企... 点击进入详情页
本回答由Storm代理提供
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式