欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android开源框架——OkHttp

程序员文章站 2024-03-25 11:37:28
...

An HTTP & HTTP/2 client for Android and Java applications.
一个处理网络请求的开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献。


1. 知识回顾

1.1 HTTP协议及特点

HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web)服务器传输超文本到本地浏览器的传送协议,它是一种请求/响应式的协议,客户端在与服务器端建立连接后,即可向服务器端发送请求,这种请求被称为HTTP请求,服务器端接收到请求后会做出响应,称为HTTP响应。

Android开源框架——OkHttp

HTTP协议是一种基于TCP协议的通讯协议。由于TCP协议提供传输控制,按顺序组织数据和错误纠正,因此HTTP协议使用TCP协议而不是UDP协议。

其特点可以总结为如下几点:

  1. 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
  2. **灵活:**HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
  3. 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
  4. **无状态:**HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
  5. 支持B/S及C/S模式。

1.2 HTTP的工作方式

HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。

  1. 客户端连接到Web服务器:一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接;
  2. 发送HTTP请求:通过TCP套接字,客户端向Web服务器发送一个文本的请求报文。一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
  3. *服务器接受请求并返回HTTP响应:**Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。*
  4. 释放连接TCP连接:若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
  5. 客户端浏览器解析HTML内容:客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。

1.3 HTTP请求与响应

1.3.1 请求

HTTP请求包括:一个请求行,若干请求头,实体内容。

请求行:
  1. 请求方式:post、get、head、options、delete、trace、put,常用post、get;
  2. post、get区别:表现在数据传递上
    • get可在url地址后以?形式带上交给服务器的数据,多个数据之间以&分隔,但数据容量不能超过1k;
    • post可在请求的实体中向服务器发送请求,传送数据量无限制。
请求头
  • Accept:告诉服务器 客户机支持的数据类型
  • Accept-Charset:告诉服务器,客户机采用的编码
  • Accept-Encoding:告诉服务器,客户机支持的压缩格式
  • Host:客户机通过这个头告诉服务器想访问的主机
  • Referer:客户机通过这个头告诉服务器,它是从哪个资源来访问服务器(防盗链)
  • User-Agent:告诉服务器客户机的软件环境
  • Cookie:可以向服务器带数据
  • Connection:是否保持长连接,Keep-Alive表示保持长连接

1.3.2 响应

HTTP响应头:一个状态行、若干消息头、以及实体内容。

状态行:
  1. 格式:HTTP版本号 状态码 原因叙述
    状态码用于表示服务器对请求的处理结果,为三位的十进制数,响应状态码分5类:
    • 100-199
    • 200-299
      200:表示服务器成功处理了客户端的请求;
    • 300-399:为完成请求,客户需进一步细化请求,
      302 表示请求的资源临时从不同的URI响应请求,但请求者应继续使用原有位置进行以后的请求。
      304/307:拿缓存;
    • 400-499:客户端请求有错误,常用404,403,
      404:表示服务器找不到请求的资源;
      403:客户端没有权限访问服务器;
    • 500-599
      500:服务器端出现错误
响应头
  • Location:这个头配合302状态使用,用于告诉客户机找谁
  • Server:服务器通过这个头告诉浏览器服务器的类型
  • Content-Encoding:服务器通过这个头告诉浏览器数据的压缩格式
  • Content-Type:服务器通过这个头告诉浏览器回送数据的类型(数据类型表示服务器告诉浏览器将怎样显示数据,是以图片显示,还是文字显示)
  • Last-Modified:服务器通过这个头浏览器告诉当前资源缓存时间
  • Refresh:服务器通过这个头告诉浏览器隔多长时间刷新一次;
  • Content-Disposition:服务器通过这个头告诉浏览器以下载方式打开数据
  • Transfer-Encoding:服务器通过这个头告诉浏览器数据的传送格式
  • Cache-Control:no-cache

2. OkHttp

OkHttp不仅具有高效的请求效率, 并且提供了很多开箱即用的网络疑难杂症解决方案。

  • 支持HTTP/2。HTTP/2通过使用多路复用技术在一个单独的TCP连接上支持并发, 通过在一个连接上一次性发送多个请求来发送或接收数据 ;
  • 如果HTTP/2不可用, 连接池复用技术也可以极大减少延时;
  • 支持GZIP, 可以压缩下载体积 ;
  • 响应缓存可以直接避免重复请求 ;
  • 会从很多常用的连接问题中自动恢复;
  • 如果您的服务器配置了多个IP地址, 当第一个IP连接失败的时候, OkHttp会自动尝试下一个IP;
  • OkHttp还处理了代理服务器问题和SSL握手失败问题。

使用 OkHttp 无需重写您程序中的网络代码。OkHttp实现了几乎和java.net.HttpURLConnection一样的API。

2.1 配置方法

在android程序里,我们一般用Gradle:

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

2.2 一般的使用办法

  1. 创建一个OkHttpClient对象;
  2. 创建一个Request对象,通过内部类Builder调用生成Request对象;
  3. 创建一个Call对象,调用execute/enqueue。

2.2.1 Get请求

  1. 先实例化okhttp,构建一个request,使用的是get方式,放入一个url地址就可以了,也可以通过Request.Builder设置更多的参数。
  2. 然后通过client发起一个请求,放入队列。等待任务完成,在Callback中取结果。
  3. 通过response.body().string()获取返回来的字符串。
OkHttpClient client = new OkHttpClient();
        //创建一个Request
        Request request = new Request.Builder()
                .get()
                .url(url)
                .build();
        //通过client发起请求
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                // String str = response.body().string();
                }

            }
        });

2.2.2 Post请求

  • From表单形式
OkHttpClient client = new OkHttpClient();
        RequestBody body = new FormBody.Builder().add("username","xiaoyi").build();
        Request request = new Request.Builder()
                .post(body)
                .url(url).
                build();
        client.newCall(request).enqueue(new Callback() {...});
  • JSON参数形式
OkHttpClient client = new OkHttpClient();
        RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
        Request request = new Request.Builder()
                .post(body)
                .url(url).
                        build();
        client.newCall(request).enqueue(new Callback() {...});

2.2.3 文件上传

OkHttpClient client = new OkHttpClient();
        RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), fiDatale);
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", "head_img", fileBody)
                .addFormDataPart("name", "xiaoyi").build();

        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();

        client.newCall(request).enqueue(new Callback() {...});

2.2.4 文件下载

OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()){
                    downlodefile(response, Environment.getExternalStorageDirectory().getAbsolutePath(),"text.txt");
                }
            }
        });

2.2.5 Interceptors

Interceptors是Okhttp中的拦截器,官方介绍拦截器是一个强大的监听器,可以重写。

Android开源框架——OkHttp

  1. 橙色框内是okhttp自带的Interceptors的实现类,它们都是在call.getResponseWithInterceptorChain()中被添加入 InterceptorChain中,实际上这几个Interceptor都是在okhttp3后才被引入,它们非常重要,负责了重连、组装请求头部、读/写缓存、建立socket连接、向服务器发送请求/接收响应的全部过程。
  2. 在okhttp3之前,这些行为都封装在HttpEngine类中。okhttp3之后,HttpEngine已经被删去,取而代之的是这5个Interceptor,可以说一次网络请求中的细节被解耦放在不同的Interceptor中,不同Interceptor只负责自己的那一环节工作(对Request或者Response进行获取/处理),使得拦截器模式完全贯穿整个网络请求。

  3. 用户可以添加自定义的Interceptor,okhttp把拦截器分为应用拦截器和网络拦截器

 public class OkHttpClient implements Cloneable, Call.Factory {
  final List<Interceptor> interceptors;
  final List<Interceptor> networkInterceptors;
  ......
  }
  • 调用OkHttpClient.Builder的addInterceptor()可以添加应用拦截器,只会被调用一次,可以处理网络请求回来的最终Response
  • 调用addNetworkInterceptor()可以添加network拦截器,处理所有的网络响应(一次请求如果发生了redirect ,那么这个拦截器的逻辑可能会被调用两次)

    1. Application interceptors与Network Interceptors

Android开源框架——OkHttp


参考并感谢:

  1. OkHttp用法
  2. OkHttp使用完全教程
  3. okhttp
相关标签: OkHttp