内部使用了OKIO库, 此库中Source表示输入流(相当于InputStream),Sink表示输出流(相当于OutputStream)

特点:

·既支持同步请求,也支持异步请求,同步请求会阻塞当前线程,异步请求不阻塞当前线程,异步执行完成后回掉相应的方法

·支持HTTP/2协议,通过HTTP/2 可以让客户端中到服务器的所有请求共用同一个Socket连接

·非HTTP/2 请求时, OKHTTP内部会维护一个线程池,通过线程池可以对HTTP/1.x的连接进行复用,减少延迟

·透明的Gzip处理降低了通信数据的大小

·请求的数据可以进行缓存

重要的类:

·Request 请求类,OKHTTP中大量使用了Builder构建器模式,Request也不例外,其内部有静态内部类Builder, 封装了请求url,请求方法method,请求头headers, 请求体RequestBody,请求标记tag

·Headers类, 被封装在Request或Response中,其内部使用一维数组String[] namesAndValues表示header的key value信息,可以看到除了导入包中的Util、HttpDate类之外,跟OKHTTP的关联并不大,可以将此类copy出来单独分析。在Builder内部类中有一个ArrayList<String> namesAndValues

,当我们添加header键值对时,调用add方法,最终调用addLenient()方法将name,value的值依次添加到列表中,列表内部按照name,value,name2,value2,name3,value3...的顺序排列,在build()方法中调用toArray方法再转换为String数组,内部元素的顺序不变,这样在用get方法查找的时候

private static String get(String[] namesAndValues, String name) {
for (int i = namesAndValues.length - 2; i >= 0; i -= 2) {
if (name.equalsIgnoreCase(namesAndValues[i])) {
return namesAndValues[i + 1];
}
}
return null;
}

  

可以先查找对应的name,得到name对应的索引后,那么value是紧随name其后的,自然可以得到value的值。且在查找的时候i的值可以每隔2做一次处理。这样有些巧妙的设计,避免使用Map去存储键值对,一定程度上提高了效率。 由于在调用get方法时是倒序查找,故添加相同的字段时,取最后一个的值。如果使用set(String name, String value) 则会移除旧的name和value。需要注意的是有时候响应头含有多个重复name的header, 比如有个多 Set-Cookie,这时候可以调用 values(String name)便可以获得多个值。

·ResponseBody 内部使用了OKIO, 可以得到字节数组 bytes(), 字符串结果string(),或者是输入流 byteStream, 特别需要注意的是bytes() string() 方法的注释,这两个方法会将响应实体内容全部加载到内存中,所以如果响应实体比较大的话,应该考虑使用流的形式读取。其中charStream()使用响应头Content-Type指定的字符集来解析响应体。默认是UTF-8

Call

同步方法execute() 会阻塞当前线程直到有响应。

异步方法 enqueue(Callback responseCallback)

OKHttpClient

内部也使用Builder构建器模式,可以配置超时时间,缓存,代理,拦截器等

Force a Network Response

在某些情形下,例如点击了刷新按钮之后,有必要跳过缓存,直接向服务器获取资源,为了获得刷新后的资源可以 添加 Connection.addRequestProperty(“Cache-Control”, “no-cache”), 或者可以直接使用 connection.addRequestProperty(“Cache-Control”, “max-age=0”);

Force a Cache Response

Connection.addRequestProperty(“Cache-Control”, “only-if-cached”);

请求的流程:

·异步请求

创建Request ,执行client.newCall(request).enqueue(Callback)方法,跟踪newCall方法,方法内部new了一个RealCall,RealCall实现了Call接口,查看RealCall的enqueue方法,最终调用client.dispatcher().enqueue(new AsyncCall(responseCallback);其中Dispatcher内部封装了线程池(可以看到默认的线程池也是没有核心线程, 和Android-Async-http的默认线程池一致),查看Dispatcher的enqueue方法可以看到如果正在请求的call数量小于最大请求数,则将call添加到runningAsyncCalls中,并提交call到线程池中(AsyncCall实现了Runnable的接口), 查看AsyncCall的构造方法,可以看到传入响应的回调,AsyncCall提交到线程池中后,run方法中会调用execute方法,

在AsyncCall的execute方法中通过getResponseWithInterceptorChain()方法得到Response,并进行响应的请求成功或失败的回调,然后调用finished方法移除之前添加到Queue中的call。

上传文件:

OkHttpClient httpClient = new OkHttpClient();

RequestBody requestBody = FormBody.create(MediaType.parse("image/jpeg"),
new File(getExternalCacheDir()+ File.separator +"IMG_20171106_202814.jpg")); MultipartBody multipartBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("uploadimg", "IMG_20171106_202814.jpg", requestBody)
.build(); Request request = new Request.Builder().url("http://www.chuantu.biz/upload.php")
.addHeader("Cache-Control", "max-age=0")
.addHeader("Upgrade-Insecure-Requests", "1")
.addHeader("Accept-Language","zh-CN,zh;q=0.8")
.post(multipartBody).build(); Call call = httpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
} @Override
public void onResponse(Call call, Response response) throws IOException { Log.d("song", response.body().string());
}
});

  

Fidddler抓包的截图

OKHTTP 简单分析的更多相关文章

  1. Okhttp之CallServerInterceptor简单分析

    在Okhttp源码分析专栏的几篇博客分析了Okhttp几个拦截器的主要功能,还剩下最后一个拦截器CallServerInterceptor没有分析,本篇博客就简单分析下该拦截器的功能. 在Okhttp ...

  2. Okhttp对http2的支持简单分析

    在< Okhttp之RealConnection建立链接简单分析>一文中简单的分析了RealConnection的connect方法的作用:打开一个TCP链接或者打开一个隧道链接,在打开t ...

  3. Okhttp之RealConnection建立链接简单分析

    在之前的博客中我们知道Okhttp在发起链接请求先从链接池中获取连接,如果链接池中没有链接则创建新的链接RealConnection对象,然后执行其connet方法打开SOCKET链接(详见< ...

  4. Okhttp之连接池ConnectionPool简单分析(一)

    开篇声明:由于本篇博文用到的一些观点或者结论在之前的博文中都已经分析过,所以本篇博文直接拿来用,建议读此博文的Monkey们按照下面的顺序读一下博主以下博文,以便于对此篇博文的理解: <Okht ...

  5. OkHttp之ConnectInterceptor简单分析

    在< Okhttp之CacheInterceptor简单分析 >这篇博客中简单的分析了下缓存拦截器的工作原理,通过此博客我们知道在执行完CacheInterceptor之后会执行下一个浏览 ...

  6. Okhttp之CacheInterceptor简单分析

    <OkHttp之BridgeInterceptor简单分析 >简单分析了BridgeInterceptor的工作原理,在Okhttp的拦截器链上BridgeInterceptor的下一个拦 ...

  7. OkHttp之BridgeInterceptor简单分析

    在< Okhttp源码简单解析(一) >这篇博客简单分析了Okhttp请求的执行流程,通过该篇博客我们知道OkHttp的核心网络请求中内置"拦截器"发挥了重大作用:本篇 ...

  8. 简单分析JavaScript中的面向对象

    初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...

  9. CSipSimple 简单分析

    简介 CSipSimple是一款可以在android手机上使用的支持sip的网络电话软件,可以在上面设置使用callda网络电话.连接使用方式最好是使用wifi,或者3g这样上网速度快,打起电话来效果 ...

随机推荐

  1. MongoDB小结01 - MongoDB简介

    我们为什么要去学习MongoDB MongoDB是一种强大.灵活.可扩展的数据存储方式. 丰富的数据模型 MongoDB是面向文档的数据库,不是关系型数据库.它将原来'行'(row)的概念换成了更加灵 ...

  2. Windows 2008 R2 SP1部署WSUS 3.0 SP2

    1 实验环境 1)域: 域名为fengxja.com: 网段:192.168.0网段,不连接外网. 域功能级别和林功能级别为Windows server 2003模式. 2)DC服务器: 域控制器: ...

  3. 网络安全-安全散列函数,信息摘要SHA-1,MD5原理

    -----------------------------------------------欢迎查看网络安全连载博客-----------------------------------[网络安全] ...

  4. HDU 5407 CRB and Candies(LCM +最大素因子求逆元)

    [题目链接]pid=5407">click here~~ [题目大意]求LCM(Cn0,Cn1,Cn2....Cnn)%MOD 的值 [思路]来图更直观: 这个究竟是怎样推出的.说实话 ...

  5. 关于使用data()获取自定义属性出现undefined的说明

    这应该是这个函数的一个bug,没有考虑到驼峰式的写法,当我写成驼峰式,即是有大小写的变量时就会出现没有定义的情况. 今天写个交互,需要用到自定义属性,因为这个自定义属性是当作字段用的,就直接用了字段名 ...

  6. ibatis 入门

     iBatis 简单介绍: iBatis 是apache 的一个开源项目.一个O/R Mapping 解决方式,iBatis 最大的特点就是小巧.上手非常快.假设不须要太多复杂的功能.iBatis ...

  7. cocos2d-x 3.0游戏实例学习笔记 《跑酷》 第五步--button控制主角Jump&amp;Crouch

    说明:这里是借鉴:晓风残月前辈的博客.他是将泰然网的跑酷教程,用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记 ...

  8. Wget下载多个链接

    需要wget下载多个文件链接时,可以采用如下方法: 1. 将链接存入文件url.list中: 2. wget -bc -i url.list -o [log_file] -P [target_dir] ...

  9. 关于jiffies回绕以及time_after,time_before

    系统中有非常多变量用来记录一个单调递增的现实,典型的有两个,一个是TCP的序列号.还有一个就是jiffies,可是由于计算机内表示的数字都是有限无界的,所以不论什么数字都不能做到全然意义的单调递增,它 ...

  10. ios7 UIBarButtonItem 默认蓝色

    [self.navigationItem setLeftBarButtonItem:leftButton]; 这样设置在ios7上button默认是蓝色 解决方法: leftButton.tintCo ...