okhttp

OkHttp 封装了请求和缓存和缓存

OkHttp是一个相对成熟的解决方案,据说Android4.4的源码中可以看到HttpURLConnection已经替换成OkHttp实现了。所以我们更有理由相信OkHttp的强大。

OkHttp 处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败问题。

使用 OkHttp 无需重写您程序中的网络代码。OkHttp实现了几乎和HttpURLConnection一样的API。如果你用了 Apache HttpClient,则OkHttp也提供了一个对应的okhttp-apache 模块。

OkHttp 和 fresco  retrofit 等第三方库能很好的衔接。

Okhttp作为HTTP引擎,retrofit作为restful业务架构实现;目前retrofit的restful风格规范是趋势。

OkHttp是一个高效的Http客户端

  1. 支持HTTP2/SPDY黑科技
  2. socket自动选择最好路线,并支持自动重连
  3. 拥有自动维护的socket连接池,减少握手次数
  4. 拥有队列线程池,轻松写并发
  5. 拥有Interceptors轻松处理请求与响应(比如透明GZIP压缩,LOGGING)
  6. 基于Headers的缓存策略

注:什么是SPDY

SPDY(读作“SPeeDY”)是Google开发的基于TCP的传输层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强。新协议的功能包括数据流的多路复用、请求优先级以及HTTP报头压缩。谷歌表示,引入SPDY协议后,在实验室测试中页面加载速度比原先快64%。中文名:spdy协议,目前SPDY已经被Http/2代替,google已经宣布要移除SPDY;

主要对象

  • Connections: 对JDK中的socket进行了引用计数封装,用来控制socket连接
  • Streams: 维护HTTP的流,用来对Requset/Response进行IO操作
  • Calls: HTTP请求任务封装
  • StreamAllocation: 用来控制Connections/Streams的资源分配与释放

工作流程的概述

当我们用OkHttpClient.newCall(request)进行execute/enenqueue时,实际是将请求Call放到了Dispatcher中,okhttp使用Dispatcher进行线程分发,它有两种方法,一个是普通的同步单线程;另一种是使用了队列进行并发任务的分发(Dispatch)与回调,我们下面主要分析第二种,也就是队列这种情况,这也是okhttp能够竞争过其它库的核心功能之一; 

Socket管理(StreamAllocation)

经过上一步的分配,我们现在需要进行连接了。我们目前有封装好的Request,而进行HTTP连接需要进行Socket握手,Socket握手的前提是根据域名或代理确定Socket的ip与端口。这个环节主要讲了http的握手过程与连接池的管理,分析的对象主要是StreamAllocation。

Githug:  https://github.com/square/okhttp

wiki:https://github.com/square/okhttp/wiki

中文翻译wiki

OKHttp源码解析

配置方法:

注意:okhttp内部依赖okio,别忘了同时导入okio

(1)Android Studio:

1 compile 'com.squareup.okhttp:okhttp:2.4.0'

导入okio:

1 compile 'com.squareup.okio:okio:1.5.0'

(2)Eclipse:

可以下载最新的jar okhttp he latest JAR ,添加依赖就可以用了

最新的jar地址:okio the latest JAR

使用:

1 //创建okHttpClient对象
2 OkHttpClient mOkHttpClient = new OkHttpClient();
3 // 创建Request.Builder  post请求方式
4 Request.Builder builder = new Request.Builder().post()
5                 .url("https://github.com/hongyangAndroid");
6 //创建一个Request
7 final Request request = builder.build();
8 //通过请求request,构造出call
9 Call call = mOkHttpClient.newCall(request); 

(1)Request.Builder

通过Request.Builder设置更多的参数比如:

(1) 添加请求头header:

如果它本身存在值,在添加新的value之前,他们会被移除。使用addHeader(name, value)来添加头部不需要移除当前存在的headers。

1 builder.addHeader("SYSVERSION",  "1.01");

当写请求头,构造时用header(name, value)来为唯一出现的name设置value。

1 Request.Builder builder = new Request.Builder().post()
2                  .url("https://github.com/hongyangAndroid")
3                  .header("Cookie", "OkHttpUser");

(2)添加method

请求携带参数:

post方式:

发布表单参数

 1 String url = url;
 2 // 创建builder
 3 FormBody.Builder builder = new FormBody.Builder();
 4 requestBody.add("user", "charles");
 5 requestBody.add("age", "12");
 6 // 创建RequestBody
 7 RequestBody requestBody = builder.build();
 8 
 9 Request request = new Request.Builder().post(requestBody ).url(url).build();
10 Response response = mOKHttpClient.newCall(request).execute();

发布multipart请求

MultipartBody.Builder可以构建与HTML文件上传表单兼容的复杂请求主体。例如文件上传

视频类:MediaType.parse("application/octet-stream")

 1 File file = new File(Environment.getExternalStorageDirectory(), "about.jpg");
 2 
 3 RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), file);
 4 
 5 RequestBody requestBody = new MultipartBuilder()
 6      .type(MultipartBuilder.FORM)
 7      .addPart(Headers.of(
 8           "Content-Disposition", 
 9               "form-data; name="username""), 
10           RequestBody.create(null, "charles"))
11      .addPart(Headers.of(
12          "Content-Disposition", 
13          "form-data; name="imagefile"; 
14          filename="aboutApp.jpg""), fileBody)
15      .build();
16 
17 Request request = new Request.Builder()
18     .url("http://.../fileUpload")
19     .post(requestBody)
20     .build();
21 
22 Reponse reponse = mOkHttpClient.newCall(request).execute();

get方式:

1 String url = url + "?" + "user=charles" + "&age=12" 
2 Request request = new Request.Builder().get().url(url).build();
3 Response response = mOKHttpClient.newCall(request).execute();

执行call:

(1)异步

调用call.enqueue,将call加入调度队列,等待任务执行完成,在Callback中即可得到结果。

 1 // 异步执行call
 2 call.enqueue(new Callback()
 3         {
 4             @Override
 5             public void onFailure(Request request, IOException e)
 6             {
 7             }
 8 
 9             @Override
10             public void onResponse(final Response response) throws IOException
11             {
12                  String htmlStr =  response.body().string();// 当前线程不是ui线程
13             }
14         });  

(2)同步,阻塞方式:

1 Response response = call.execute();

Response:

(1)返回字符串,通过response.body().string()获取;

(2)返回二进制字节数组,通过response.body().bytes()获取

(3)返回inputStream,通过response.body().byteStream()获取 (支持大文件下载);

原文地址:https://www.cnblogs.com/CharlesGrant/p/6512712.html