OkHttp3源码详解(一) Request类,聪明人已经收藏了

  1. public String encodedName(int index) {

  2. return encodedNames.get(index);

  3. }

  4. public String name(int index) {

  5. return percentDecode(encodedName(index), true);

  6. }

  7. public String encodedValue(int index) {

  8. return encodedValues.get(index);

  9. }

  10. public String value(int index) {

  11. return percentDecode(encodedValue(index), true);

  12. }

  13. @Override public MediaType contentType() {

  14. return CONTENT_TYPE;

  15. }

  16. @Override public long contentLength() {

  17. return writeOrCountBytes(null, true);

  18. }

  19. @Override public void writeTo(BufferedSink sink) throws IOException {

  20. writeOrCountBytes(sink, false);

  21. }

  22. /**

    • Either writes this request to {@code sink} or measures its content length. We have one method
    • do double-duty to make sure the counting and content are consistent, particularly when it comes
    • to awkward operations like measuring the encoded length of header strings, or the
    • length-in-digits of an encoded integer.
  23. */

  24. private long writeOrCountBytes(BufferedSink sink, boolean countBytes) {

  25. long byteCount = 0L;

  26. Buffer buffer;

  27. if (countBytes) {

  28. buffer = new Buffer();

  29. } else {

  30. buffer = sink.buffer();

  31. }

  32. , size = encodedNames.size(); i < size; i++) {

  33. ) buffer.writeByte(‘&’);

  34. buffer.writeUtf8(encodedNames.get(i));

  35. buffer.writeByte(‘=’);

  36. buffer.writeUtf8(encodedValues.get(i));

  37. }

  38. if (countBytes) {

  39. byteCount = buffer.size();

  40. buffer.clear();

  41. }

  42. return byteCount;

  43. }

  44. public static final class Builder {

  45. private final List names = new ArrayList<>();

  46. private final List values = new ArrayList<>();

  47. public Builder add(String name, String value) {

  48. names.add(HttpUrl.canonicalize(name, FORM_ENCODE_SET, false, false, true, true));

  49. values.add(HttpUrl.canonicalize(value, FORM_ENCODE_SET, false, false, true, true));

  50. return this;

  51. }

  52. public Builder addEncoded(String name, String value) {

  53. names.add(HttpUrl.canonicalize(name, FORM_ENCODE_SET, true, false, true, true));

  54. values.add(HttpUrl.canonicalize(value, FORM_ENCODE_SET, true, false, true, true));

  55. return this;

  56. }

  57. public FormBody build() {

  58. return new FormBody(names, values);

  59. }

  60. }

  61. }

``````````````我们主要来看一下方法````````````````writeOrCountBytes``````````````````````````````,通过writeOrCountBytes来计算请求体大小和将请求体写入BufferedSink。

至于BufferSink和Buffer类,这两个类是Okio中的类,Buffer相当于一个缓存区,BufferedSink相当于OutputStream,它扩展了

OutputStream的功能,Okio的完整源码我后续也会写博客

③方式三:MultipartBody分块表单创建

``MultipartBody, 既可以添加表单,又可以也可以添加文件等二进制数据,我们就看几个重要的方法

  1. public static Part createFormData(String name, String filename, RequestBody body) {

  2. if (name == null) {

  3. throw new NullPointerException(“name == null”);

  4. }

  5. StringBuilder disposition = new StringBuilder(“form-data; name=”);

  6. appendQuotedString(disposition, name);

  7. if (filename != null) {

  8. disposition.append(“; filename=”);

  9. appendQuotedString(disposition, filename);

  10. }

  11. return create(Headers.of(“Content-Disposition”, disposition.toString()), body);

  12. }

我们来看这个方法,我们是addPart还是addFormDataPart最终都走到了这个方法,封装成一个Part对象,也就是实体内容中

的Content-Disposition跟文件二进制流或者键值对的值

````````````````MultipartBody和FormBody大体上相同,主要区别在于`writeOrCountBytes方法,分块表单主要是将每个块的大小进行累加来求出请求体大小,如果其中有一个块没有指定大小,就会返回-1。所以分块表单中如果包含文件,默认是无法计算出大小的,除非你自己给文件的RequestBody指定contentLength。`````````````````

  1. private long writeOrCountBytes(BufferedSink sink, boolean countBytes) throws IOException {

  2. long byteCount = 0L;

  3. Buffer byteCountBuffer = null;

  4. if (countBytes) {

  5. //如果是计算大小的话,就new个

  6. sink = byteCountBuffer = new Buffer();

  7. }

  8. //循环块

  9. , partCount = parts.size(); p < partCount; p++) {

  10. Part part = parts.get§;

  11. //获取每个块的头

  12. Headers headers = part.headers;

  13. //获取每个块的请求体

  14. RequestBody body = part.body;

  15. //写 --xxxxxxxxxx 边界

  16. sink.write(DASHDASH);

  17. sink.write(boundary);

  18. sink.write(CRLF);

  19. //写块的头

  20. if (headers != null) {

  21. , headerCount = headers.size(); h < headerCount; h++) {

  22. sink.writeUtf8(headers.name(h))

  23. .write(COLONSPACE)

  24. .writeUtf8(headers.value(h))

  25. .write(CRLF);

  26. }

  27. }

  28. //写块的Content_Type

  29. MediaType contentType = body.contentType();

  30. if (contentType != null) {

  31. sink.writeUtf8("Content-Type: ")

  32. .writeUtf8(contentType.toString())

  33. .write(CRLF);

  34. }

  35. //写块的大小

  36. long contentLength = body.contentLength();

  37. ) {

  38. sink.writeUtf8("Content-Length: ")

  39. .writeDecimalLong(contentLength)

  40. .write(CRLF);

  41. } else if (countBytes) {

  42. // We can’t measure the body’s size without the sizes of its components.

  43. //如果有个块没有这名大小,就返回-1.

  44. byteCountBuffer.clear();

  45. return -1L;

  46. }

  47. sink.write(CRLF);

  48. //如果是计算大小就累加,否则写入BufferedSink

  49. if (countBytes) {

  50. byteCount += contentLength;

  51. } else {

  52. body.writeTo(sink);

  53. }

  54. sink.write(CRLF);

  55. }

  56. //写 --xxxxxxxxxx-- 结束边界

  57. sink.write(DASHDASH);

  58. sink.write(boundary);

  59. sink.write(DASHDASH);

  60. sink.write(CRLF);

  61. if (countBytes) {

  62. byteCount += byteCountBuffer.size();

  63. byteCountBuffer.clear();

  64. }

  65. return byteCount;

  66. }

4.CacheControl

( 1)  Cache-Control:

Cache-Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令有下几种:

  1. Public:所有内容都将被缓存(客户端和代理服务器都可缓存)。

  2. Private:内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可缓存)

  3. no-cache:请求或者响应消息不能缓存

  4. no-store:不使用缓存,也不存储缓存

  5. max-age:缓存的内容将在指定时间(秒)后失效, 这个选项只在HTTP 1.1可用, 并如果和Last-Modified一起使用时, 优先级较高

  6. 在 xxx 秒后,浏览器重新发送请求到服务器,指定时间(秒)内,客户端会直接返回cache而不会发起网络请求,若过期会自动发起网络请求

  7. min-fresh:指示客户端可以接收响应时间小于当前时间加上指定时间的响应。

  8. max-stale:指示客户端可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。

(2)CacheControl类

①常用的函数

  1. final CacheControl.Builder builder = new CacheControl.Builder();

  2. builder.noCache();//不使用缓存,全部走网络

  3. builder.noStore();//不使用缓存,也不存储缓存

  4. builder.onlyIfCached();//只使用缓存

  5. builder.noTransform();//禁止转码

  6. builder.maxAge(, TimeUnit.MILLISECONDS);//指示客户机可以接收生存期不大于指定时间的响应。

  7. builder.maxStale(, TimeUnit.SECONDS);//指示客户机可以接收超出超时期间的响应消息

  8. builder.minFresh(, TimeUnit.SECONDS);//指示客户机可以接收响应时间小于当前时间加上指定时间的响应。

  9. CacheControl cache = builder.build();//cacheControl

②CacheControl的两个常量:

  1. public static final CacheControl FORCE_NETWORK = new Builder().noCache().build();//不使用缓存

  2. public static final CacheControl FORCE_CACHE = new Builder()

  3. .onlyIfCached()

  4. .maxStale(Integer.MAX_VALUE, TimeUnit.SECONDS)

  5. .build();//只使用缓存

③请求时如何使用:

  1. final CacheControl.Builder builder = new CacheControl.Builder();

  2. builder.maxAge(, TimeUnit.MILLISECONDS);

  3. CacheControl cache = builder.build();

  4. final Request request = new Request.Builder().cacheControl(cache).url(requestUrl).build();

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

小结

有了这么多优秀的开发工具,可以做出更高质量的Android应用。

当然了,“打铁还需自身硬”,想要写出优秀的代码,最重要的一点还是自身的技术水平,不然用再好的工具也不能发挥出它的全部实力。

在这里我也分享一份大佬自己收录整理的Android学习PDF+架构视频+面试文档+源码笔记,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。

总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

链图片转存中…(img-baEwDs6u-1710846255684)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-WR2Eb8FL-1710846255685)]

小结

有了这么多优秀的开发工具,可以做出更高质量的Android应用。

当然了,“打铁还需自身硬”,想要写出优秀的代码,最重要的一点还是自身的技术水平,不然用再好的工具也不能发挥出它的全部实力。

在这里我也分享一份大佬自己收录整理的Android学习PDF+架构视频+面试文档+源码笔记,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。

总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

如果你有需要的话,可以点击这里领取

  • 16
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值