美文网首页
【Android】【框架】【网络】【OkHttp】

【Android】【框架】【网络】【OkHttp】

作者: 徐乙_ | 来源:发表于2019-08-05 23:44 被阅读0次

使用

1、接入

implementation 'com.squareup.okhttp3:okhttp:3.10.0'

2、使用

// OkHttpClient初始化,全局仅需初始化一次
OkHttpClient okHttpClient = new OkHttpClient();

// 构建请求
final Request request = new Request.Builder()
        .url("http://wwww.baidu.com")
        .build();

// 发起异步请求
client.newCall(request)
  .enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {}

    @Override
    public void onResponse(Call call, Response response) throws IOException {}
});

架构

1、主体架构

image.png

第一步在Deque中保存,同步请求有1个队列,异步请求会在2个队列中进行流转,防止创建太多线程(单个host请求<5,总请求<64,入执行中队列)
第二步被Dispatcher分发到线程池中,这个线程池全为核心线程,任何一个线程60s不用,就会被“关闭”
第三步被若干拦截器进行处理

拦截器

1、执行顺序
自定义应用拦截器
重试、重定向拦截器
应用/网络桥接拦截器
缓存拦截器
连接拦截器
自定义网络拦截器
实际网络请求拦截器
2、自定义
自定义应用拦截器不用赘述,为何还要有个自定义网络拦截器?
举个例子,缓存拦截器根据Http不同版本的字段来做缓存,这些字段由服务端下发,控制客户端缓存行为。
这个时候有这样一个拦截器,就可以修改Http缓存字段,甚至手动做缓存。
其实就是像Charles一样,给人一种Mock的感觉。
3、Retry & ReDirect
本质上是一个while循环,不断发起请求
重试是通过内层拦截器执行时抛出的异常,得知需要再次发起请求
重定向是根据服务端返回的错误码301,再次发起请求
由于者2者功能几乎一致,所以把他们的功能写到了同一个拦截器里
4、Bridge
我们请求时填写的数据仅仅是业务数据,而非真正的Http请求,这一步帮我们填充真正请求要有的字段,如:
contentLength、编码 、gzip压缩、cookie 、header(User-Agent,Host,Keep-alive等)
5、Cache
使用了策略模式
基于DiskLRUCache做缓存
其逻辑和Http缓存规则基本一致
6、Connect
这块值得一讲的是连接池,连接池中找到一个可用的连接,并创建HttpCodec对象,内部用Okio封装了Socket处理
通过计数+标记清理的机制来管理连接池 ,使得无用连接可以被会回收,并保持多个健康的keep-alive连接
还有多路复用的实现:老HTTP要频繁挥手握手。而多路复用,可以保持连接,而且进行了压缩,还可以分帧
7、CallServer
之前的拦截器都是在做数据处理,把我们的业务数据,由Http协议数据包裹
这个拦截器就是基于Socket进行数据传递
而Socket处理都被封装在Okio之中

Okio

Okio没有涉及NIO、AIO,只是基于BIO的封装
但是做了一些措施,优化了性能,如:
维护一个双向链表,每个元素都是一小段数组,这整个链表作为缓存池,用于做IO时的缓冲区,这样精妙的涉及,使得不管是内存消耗还是CPU消耗,都得到了不小的提升
另有ByteString用于处理不可变对象,同时缓存了String以及byte数组,转型起来不费时间
看门狗机制,用于检测IO超时,基于阻塞/唤醒机制,保证了线程资源的充分利用

可优化的点

  1. 调用冗余,需要二次封装。推荐的封装框架是 Retrofit + RxJava,不管是调用上、还是项目的可维护性上,都是最佳的。
  2. 可以较好地cover大部分的网络请求case,但是对于连接、线程的复用,做得还是太简单了一些,如果希望网络请求能力进一步提升,可以根据业务类型,从长连接、网络协议选型、线程管理等方面做进一步的优化

收获

  1. 拦截器:如果你开发一个库,各个功能等级相仿,且服务于同一目标,不妨使用拦截器模式
  2. 池技术:Okio的池技术使用得很好,其双向链表容结合数组单元的操作令人佩服,对性能有了不小的优化,以后开发,也可以用池技术,结合高性能的数据结构,写出性能更棒的代码
  3. wait/notify机制:Okio通过看门狗监控IO超时,是很经典的阻塞唤醒机制,极大地节省了CPU。这点和Handler(epoll)的机制很相似。这也是性能优化的方向。
  4. 队列+线程池处理异步请求。这里使用的是高性能的循环链表Deque作为队列,控制了请求并发上线,防止了线程池中线程的无限创建,过度消耗系统资源。

后记

学习自
https://yq.aliyun.com/articles/78105?spm=a2c4e.11153940.blogcont78104.10.5e046a7d9HLSog
https://www.jianshu.com/p/fa0dcbfe05cd
https://blog.csdn.net/qq_36523667/article/details/81006303
https://blog.csdn.net/qq_36523667/article/details/79618069

有什么写得错误、让人费解或遗漏的地方,希望可以不吝赐教,我会马上更改

相关文章

网友评论

      本文标题:【Android】【框架】【网络】【OkHttp】

      本文链接:https://www.haomeiwen.com/subject/vbkbdctx.html