okhttp使用总结
okhttp 使用总结
okhttp
的使用越来越火,有必要对其进行研究。以下博客中的例子为了简单,在Eclipse
中通过JAVA
工程进行验证。
导入OkHttp
AndroidStudio
添加如下代码即可
compile 'com.squareup.okhttp3:okhttp:3.3.1'compile 'com.squareup.okio:okio:1.8.0'
其中okio
是okhttp
中关于流的操作。必须导入。
Eclipse
导入okhttp
与okio
的jar包即可。
下载地址okhttp3.3.1与okio-1.8.0
同步的GET请求
主要分为以下几步:
- 创建
OkHttpClient
对象 - 根据需求创建
Request
对象,Request
中主要包含了请求的url,参数等信息。 - 通过
request
对象创建Call
对象 - 使用
call
对象进行网络请求。返回封装好的Response
- 解析
Response
对象,获取响应信息
/**
* 同步 Get 请求
*/
public static void syncGet() throws Exception {// 1. 创建`OkHttpClient`对象final OkHttpClient client = new OkHttpClient();// 2.根据需求创建`Request`对象.在此只是添加了最基本的urlRequest request = new Request.Builder().url(BAIDU_MP3_PATH).build();// 3.通过`request`对象创建`Call`对象Call call = client.newCall(request);// 4.使用`call`对象进行网络请求。返回封装好的`Response`Response response = call.execute();// 5.解析`Response`对象,获取响应信息if (!response.isSuccessful())// code >= 200 && code < 300;System.out.println(response);Headers responseHeaders = response.headers();for (int i = 0; i < responseHeaders.size(); i++) {System.out.println(responseHeaders.name(i) + ":"+ responseHeaders.value(i));}// 打印响应的内容System.out.println(response.body().string());}
其中使用的url为百度MP3的接口:
http://tingapi.ting.baidu.com/v1/restserver/ting?from=qianqian&version=2.1.0&method=baidu.ting.billboard.billList&format=json&type=1&offset=0&size=1
看一下打印结果:
//---- response 的toString() 默认打印的信息 响应行
Response{protocol=http/1.1, code=200, message=OK, url=http://tingapi.ting.baidu.com/v1/restserver/ting?from=qianqian&version=2.1.0&method=baidu.ting.billboard.billList&format=json&type=1&offset=0&size=1}//----- 响应的头
Date:Wed, 29 Jun 2016 01:51:39 GMT
Content-Type:application/json
Transfer-Encoding:chunked
Connection:keep-alive
X-LIGHTTPD-LOGID:427084050
RT:427084050_d41d8cd98f00b204e9800998ecf8427e_d41d8cd98f00b204e9800998ecf8427e
Server:Apache1.0
SC:MISS.0.0
tracecode:30991485713674384576062909
Set-Cookie:BAIDUID=B343E34EB3618E7E2E867A6E1D4F04EB:FG=1; expires=Thu, 29-Jun-17 01:51:39 GMT; max-age=31536000; path=/; domain=.baidu.com; version=1
P3P:CP=" OTI DSP COR IVA OUR IND COM "// ---- 响应的内容 body
{"song_list":[{"artist_id":"247010469","language":"\u56fd\u8bed","pic_big":"http:\/\/musicdata.baidu.com\/data2\/pic\/0c87cb20fd6b543cd1c90d1d82f1f6c5\/266782982\/266782982.jpg","pic_small":"http:\/\/musicdata.baidu.com\/data2\/pic\/169cbb0d82522568dea198363f7028ec\/266782985\/266782985.jpg","country":"\u5185\u5730","area":"0","publishtime":"2016-06-20","album_no":"1","lrclink":"http:\/\/musicdata.baidu.com\/data2\/lrc\/1f75306d7f1e25f723d3d175f5ef3d46\/266791084\/266791084.lrc","copy_type":"1","hot":"276927","all_artist_ting_uid":"232954914","resource_type":"0","is_new":"1","rank_change":"0","rank":"1","all_artist_id":"247010469","style":"\u6d41\u884c","del_status":"0","relate_status":"0","toneid":"0","all_rate":"64,128,256","sound_effect":"0","file_duration":0,"has_mv_mobile":1,"versions":"","bitrate_fee":"{\"0\":\"0|0\",\"1\":\"-1|-1\"}","song_id":"266784254","title":"\u7ea2","ting_uid":"232954914","author":"\u51af\u5efa\u5b87","album_id":"266784256","album_title":"\u7ea2","is_first_publish":0,"havehigh":0,"charge":0,"has_mv":1,"learn":0,"song_source":"web","piao_id":"0","korean_bb_song":"1","resource_type_ext":"1","mv_provider":"0100000000","artist_name":"\u51af\u5efa\u5b87"}],"billboard":{"billboard_type":"1","billboard_no":"1871","update_date":"2016-06-28","billboard_songnum":"190","havemore":1,"name":"\u65b0\u6b4c\u699c","comment":"\u8be5\u699c\u5355\u662f\u6839\u636e\u767e\u5ea6\u97f3\u4e50\u5e73\u53f0\u6b4c\u66f2\u6bcf\u65e5\u64ad\u653e\u91cf\u81ea\u52a8\u751f\u6210\u7684\u6570\u636e\u699c\u5355\uff0c\u7edf\u8ba1\u8303\u56f4\u4e3a\u8fd1\u671f\u53d1\u884c\u7684\u6b4c\u66f2\uff0c\u6bcf\u65e5\u66f4\u65b0\u4e00\u6b21","pic_s640":"http:\/\/c.hiphotos.baidu.com\/ting\/pic\/item\/f7246b600c33874495c4d089530fd9f9d62aa0c6.jpg","pic_s444":"http:\/\/d.hiphotos.baidu.com\/ting\/pic\/item\/78310a55b319ebc4845c84eb8026cffc1e17169f.jpg","pic_s260":"http:\/\/b.hiphotos.baidu.com\/ting\/pic\/item\/e850352ac65c1038cb0f3cb0b0119313b07e894b.jpg","pic_s210":"http:\/\/business.cdn.qianqian.com\/qianqian\/pic\/bos_client_c49310115801d43d42a98fdc357f6057.jpg","web_url":"http:\/\/music.baidu.com\/top\/new"},"error_code":22000}
如果熟悉HTTP 协议的可知,作为Http的响应,分为响应行,响应头,响应体。
如果不熟悉HTTP协议,欢迎看我之前的博客Java Web之HTTP协议总结
如上打印结果就分别对应了响应行,响应头,响应体。
注释很清楚,按照步骤即可,着重提一下解析Response
的内容。
response.isSuccessful()
,该方法在响应code为[200,300)时,返回true,其余返回false。注意区间为前闭后开。response.headers()
:获取响应行信息的所有参数的集合headers
。headers
的使用方式类似于List
。response.body().string()
:该方法返回的是响应的内容。但是,官方给出的指导是,如果响应的内容大于1MB 时,不建议使用该方法。因为该方法会将内容全部加载到内存中。推荐使用流的方式获取加载的数据。response.body().byteStream();
:字节输入流response.body().charStream();
:字符输入流
异步的GET 请求
异步GET的请求方式几乎和上面的步骤类似,唯一的区别是通过Call
对象请求网络时,不在直接返回Response
对象,而是通过接口回调的方式获取数据。当然,表面上是这样,其内部肯定有对应的线程切换。
/*** 异步的get方法*/public static void asyncGet() throws Exception {// 1. 创建`OkHttpClient`对象final OkHttpClient client = new OkHttpClient();// 2.根据需求创建`Request`对象.在此只是添加了最基本的urlRequest request = new Request.Builder().url(BAIDU_MP3_PATH).build();// 3.通过`request`对象创建`Call`对象Call call = client.newCall(request);// 4.使用`call`对象进行网络请求。通过Callback 监听网络请求call.enqueue(new Callback() {public void onResponse(Call call, Response response)throws IOException {//5, 获取响应结果并解析if (!response.isSuccessful()) {System.out.println(response);return;}Headers responseHeaders = response.headers();for (int i = 0, size = responseHeaders.size(); i < size; i++) {System.out.println(responseHeaders.name(i) + ": "+ responseHeaders.value(i));}System.out.println(response.body().string());}public void onFailure(Call call, IOException e) {System.out.println(e);}});}
此时我们使用了call.enqueue()
方法,并通过Callback
对象监听回调,其中Callback
对象中包含了两个回调方法,成功onResponse
和失败onFailure
。
肯定会有人说,我擦~~onResponse()
中为什么还要判断response.isSuccessful()
,不是已经成功了吗。
在这里这两个方法的含义和其他框架的有区别。
在这贴上该方法的注释就明白了
/*** Called when the request could not be executed due to cancellation, a connectivity problem or* timeout. Because networks can fail during an exchange, it is possible that the remote server* accepted the request before the failure.*/void onFailure(Call call, IOException e);/*** Called when the HTTP response was successfully returned by the remote server. The callback may* proceed to read the response body with {@link Response#body}. The response is still live until* its response body is {@linkplain ResponseBody closed}. The recipient of the callback may* consume the response body on another thread.** <p>Note that transport-layer success (receiving a HTTP response code, headers and body) does* not necessarily indicate application-layer success: {@code response} may still indicate an* unhappy HTTP response code like 404 or 500.*/void onResponse(Call call, Response response) throws IOException;
有能力的自己翻译,我是这样理解的。
onResponse()
:连接上了服务器,不管服务器是否有资源(404)或者服务器出bug了(500)。onFailure()
: 没有连接上服务器。(域名不存在,无网络。。。)
设置和获取响应行参数(Header)
HTTP 协议中,无论对请求和响应,都有相应的头参数。一些特别的参数能够完成一些特别的任务。类似缓存,传输编码,重定向等等。
我们知道头信息中的参数类似于Map<String,String>
,键值对的形式,但是有些特殊的头,不是一对一的,而是一对多。那么此时okHttp
肯定要有特别的方法获取这些信息。
public void accessHeader() throws Exception {final OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url("https://api.github.com/repos/square/okhttp/issues")// 只有一个参数的头 ,一对一,如果在添加会覆盖.header("User-Agent", "OkHttp Headers.java")// 一对多,添加的关系.addHeader("Accept", "application/json; q=0.5").addHeader("Accept", "application/vnd.github.v3+json").build();Response response = client.newCall(request).execute();if (!response.isSuccessful())throw new IOException("Unexpected code " + response);System.out.println("Server: " + response.header("Server"));System.out.println("Date: " + response.header("Date"));// 一对多的获取System.out.println("Vary: " + response.headers("Vary"));}
添加请求头信息时分为两种情况:
- 一对一: 使用header(String key,String value)
方法,相同的key值调用此方法,会覆盖之前的value。
- 一对多: 使用addHeader(String key,String value)
方法,相同的key值调用此方法,执行追加操作。
获取响应头信息时:
- 一对一: 使用
header(String key)
方法。 - 一对多: 使用
headers(String key)
方法。
POST 请求,传入一个字符串
Post请求,在构造Request
时,传入POST
的参数即可。
public static void postString() throws Exception {// post 传参类型 编码final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");// post 参数值String params = "### 三级标题";final OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url("https://api.github.com/markdown/raw").post(RequestBody.create(MEDIA_TYPE_MARKDOWN, params)).build();Response response = client.newCall(request).execute();if (!response.isSuccessful())throw new IOException("Unexpected code " + response);System.out.println(response.body().string());}
在Request.post
中传入的是RequestBody
对象,该对象的创建需要两个参数
MediaType contentType
:传入参数的类型。通常使用的是text/html; chareset=utf-8
。明白此值的含义,其实就是理解HTTP 协议中content-type
的作用:决定浏览器/服务器将以什么形式、什么编码读取这个文件。String content
:post发送的内容。
在此,参数类型使用的是text/x-markdown; charset=utf-8
,因为是调用github 的markdown的解析服务。所以传入了特定的类型。
返回结果
<h3>
<a id="user-content-三级标题" class="anchor" href="#%E4%B8%89%E7%BA%A7%E6%A0%87%E9%A2%98" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>三级标题</h3>
可见已经解析成了html 语言。
POST 文件
传入文件就是在RequestBody.creat()
中,第二个参数传入一个file
对象。
/*** 传入文件*/public static void postFile() throws Exception{final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");final OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url("https://api.github.com/markdown/raw").post(RequestBody.create(MEDIA_TYPE_MARKDOWN,new File("README.MD"))).build();// ....}
看看create
方法,对于文件干了什么。
new RequestBody() {@Override public MediaType contentType() {return contentType;}@Override public long contentLength() {return file.length();}@Override public void writeTo(BufferedSink sink) throws IOException {Source source = null;try {// ---- 读取文件source = Okio.source(file);sink.writeAll(source);} finally {Util.closeQuietly(source);}}};
该方法中,根据传入的参数创建了一个RequestBody
对象,其中writeTo
中读取了文件,source = Okio.source(file);
是square
封装的io操作库。继续深入
public static Source source(File file) throws FileNotFoundException {if (file == null) throw new IllegalArgumentException("file == null");// --- 字节输入流,读取文件return source(new FileInputStream(file));}
看到这里,就明白了,其实就是通过字节输入流,去读取文件。中间有加了基层流的转换,暂时不管。
POST form 表单(日常使用)
如上的例子中,使用RequestBody.create()
方法作为post的参数,很是麻烦。如果对于日常使用的post请求,需要些很多代码。那么理所当然的会有其子类替我们封装了这些方法。
FormBody
为ReqeustBody
的子类,主要用于常见的表单操作。
/*** post form 表单*/public static void postForm(){RequestBody formBody = new FormBody.Builder().add("name","1234").build();final OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url("https://api.github.com/markdown/raw").post(formBody).build();// .....}
通过add(String key,String value)
方法添加参数即可。
POST 实现复杂的form表单提交(上传文件)
在开发,往往会有上传用户头像等的需求,即复杂的表单。此时可以使用RequestBody
的子类MultipartBody
实现。
/*** 提交复杂的form 表单 附带文件** MultiBody*/public static void postMultipart(){/*** 上传的文件类型*/final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");/*** 参数*/RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("title","标题").addFormDataPart("image","logo.png",RequestBody.create(MEDIA_TYPE_PNG,new File("xx.png"))).build();Request request = new Request.Builder().url("xxx").post(requestBody).build();// ......}
Cache 缓存的实现
OkHttpClient
可以实现缓存,但如果我们不做任何配置(设置缓存的目录),则是没有缓存的。
看下面的例子
OkHttpClient client = new OkHttpClient.Builder().build();Request request = new Request.Builder().url("http://xxxx/login.txt")//.cacheControl(new CacheControl.Builder().noCache().build()).build();Response response1 = client.newCall(request).execute();String response1Body = response1.body().string();// 响应的结果信息System.out.println("Response 1 response: " + response1);// 缓存的响应信息System.out.println("Response 1 cache response: "+ response1.cacheResponse());// 网络请求的响应信息System.out.println("Response 1 network response: "+ response1.networkResponse());// ************第二次请求****************** Response response2 = client.newCall(request).execute();String response2Body = response2.body().string();System.out.println("Response 2 response: " + response2);System.out.println("Response 2 cache response: "+ response2.cacheResponse());System.out.println("Response 2 network response: "+ response2.networkResponse());System.out.println("Response 2 equals Response 1? "+ response1Body.equals(response2Body));
进行了两次请求,在请求之后,分别打印三个结果
- response
:最终的响应
- cacheResponse
: 缓存的响应,如果是从缓冲中取的,则该值不为null。
- networkResponse
:网络请求的响应,如果是从网络中请求的,则该值不为null。
Response 1 response: Response{protocol=http/1.1, code=200, message=OK, url=http://xxx/login.txt}
Response 1 cache response: null
Response 1 network response: Response{protocol=http/1.1, code=200, message=OK, url=http://xxx/login.txt}
Response 2 response: Response{protocol=http/1.1, code=200, message=OK, url=http://xxx/login.txt}
Response 2 cache response: null
Response 2 network response: Response{protocol=http/1.1, code=200, message=OK, url=http://xxx/login.txt}
Response 2 equals Response 1? true
会发现cache response
一直为null,而network response
一直不为null。可见使用了缓存。
修改代码,添加缓存
// 缓存的大小int cacheSize = 10 * 1024 * 1024; // 10 MiB// 缓存对象,第一个参数为缓存的目录Cache cache = new Cache(new File("cache"), cacheSize);// 设置缓存OkHttpClient client = new OkHttpClient.Builder().cache(cache).build();//.....
通过构造Cache
对象并对OkHttpClient
设置。
Response 1 response: Response{protocol=http/1.1, code=200, message=OK, url=http://xxx/login.txt}
Response 1 cache response: null
Response 1 network response: Response{protocol=http/1.1, code=200, message=OK, url=http://xxx/login.txt}
Response 2 response: Response{protocol=http/1.1, code=200, message=OK, url=http://xxx/login.txt}
Response 2 cache response: Response{protocol=http/1.1, code=200, message=OK, url=http://xxx/login.txt}
Response 2 network response: null
Response 2 equals Response 1? true
第一次请求时,缓存为null,网络请求不为null。因为初次加载,并没有缓存。
第二次时,网络请求为null。缓存不为null。直接从之前保存的缓存中获取值。
当然。此时是对所有的request
设置是否缓存,同时我们可以对每一个request
设置独属于自己的缓存。
// 不缓存Request request = new Request.Builder().url("http://xxx/login.txt").cacheControl(new CacheControl.Builder().noCache().build()).build();
通过cacheControl()
传入一个缓存的配置对象,
- 不使用缓存:
new CacheControl.Builder().noCache().build()
- 设置缓存的时长:
new CacheControl.Builder().maxAge().build()
maxAge(int maxAge, TimeUnit timeUnit)
: 时间数值,单位。
取消网络请求
当一个页面结束时,往往要结束网络请求,此时可以通过Call.cancel()
取消一个网络请求。这样做有利于节省系统资源。如果结束时,当前正在请求或响应,则会抛出一个IOException
。
也可以取消多个网络请求。
当构建请求时,使用RequestBuilder.tag(tag)
对当前请求设置一个标签。之后通过OkHttpClient.cancel(tag)
取消对应标签的请求。
超时的设置
连接超时,写入超时,读取超时是网络访问中常见的超时。
OkHttpClient client = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS)// 连接超时 10s.writeTimeout(10, TimeUnit.SECONDS) // 输入超时 10s.readTimeout(30, TimeUnit.SECONDS) // 读取超时 30s.build();
该方式是设置全局的超时规则,同样我们也可以对于不同的情况设置不同的超时选项。
关键点: 通过OkHttpClient.newBuilder()
构造一个client的复制体。注意,此复制类似于从client 扣下来一块设置不同的规则,同时复制体上设置的规则不会影响原client
。
/*** 设置不同的超时时间*/public static void singleTimeOut() throws Exception {OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url("http://xxxx").build();try {// 从client 中抠出一小块,用于单独的设置// 设置读取时间为1ms,肯定会超时OkHttpClient copy = client.newBuilder().readTimeout(1, TimeUnit.MILLISECONDS).build();Response response = copy.newCall(request).execute();System.out.println("Response 1 succeeded: " + response);} catch (IOException e) {System.out.println("Response 1 failed: " + e);}try {// 从client 中抠出一小块,用于单独的设置// 设置读取时间为3000msOkHttpClient copy = client.newBuilder().readTimeout(3000, TimeUnit.MILLISECONDS).build();Response response = copy.newCall(request).execute();System.out.println("Response 2 succeeded: " + response);} catch (IOException e) {System.out.println("Response 2 failed: " + e);}}
结果
Response 1 failed: java.net.SocketTimeoutException: Read timed outResponse 2 succeeded: Response{protocol=http/1.1, code=200, message=OK, url=http://xxx/}
Interceptor(拦截器)
Interceptor
:监听网络的请求与变化。
实现方式:
- 自定义类实现
Interceptor
接口 OkHttpClient.Builder().addInterceptor(自定义Interceptor).build()
;
作用:
- 打印网络请求的请求和响应的信息。
- 对网络请求做统一处理,列入添加共同的头信息。
打印网络请求的信息
为了方便,使用Eclipse
进行编写。
static class LoggingInterceptor implements Interceptor {public Response intercept(Chain chain) throws IOException {// 固定写法Request request = chain.request();// 固定写法Response response = chain.proceed(request);// --------Log 信息---在android 中改成Log.i()即可System.out.println("=====请求========");// 请求行System.out.println(request);// 请求头信息System.out.println(request.headers());// form 表单信息。注意,此时只对form 表单适用FormBody form = (FormBody) request.body();for (int i = 0; i < form.size(); i++) {System.out.println(form.encodedName(i) + "="+ form.encodedValue(i));}System.out.println("=====响应========");// 响应行System.out.println(response);// 响应头System.out.println(response.headers());// 响应体System.out.println(response.body().string());return response;}}
添加Interceptor
final OkHttpClient client = new OkHttpClient.Builder()// 添加Interceptor.addNetworkInterceptor(new LoggingInterceptor()).build();Request request = new Request.Builder().url(BAIDU_MP3_PATH).post(new FormBody.Builder().add("name", "123").build()).build();....
注意,使用的POST 表单提交。
看一下结果
=====请求========
Request{method=POST, url=http://tingapi.ting.baidu.com/v1/restserver/ting?from=qianqian&version=2.1.0&method=baidu.ting.billboard.billList&format=json&type=1&offset=0&size=1, tag=Request{method=POST, url=http://tingapi.ting.baidu.com/v1/restserver/ting?from=qianqian&version=2.1.0&method=baidu.ting.billboard.billList&format=json&type=1&offset=0&size=1, tag=null}}
Content-Type: application/x-www-form-urlencoded
Content-Length: 8
Host: tingapi.ting.baidu.com
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.3.1name=123
=====响应========
Response{protocol=http/1.1, code=200, message=OK, url=http://tingapi.ting.baidu.com/v1/restserver/ting?from=qianqian&version=2.1.0&method=baidu.ting.billboard.billList&format=json&type=1&offset=0&size=1}
Date: Wed, 29 Jun 2016 08:22:28 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
X-LIGHTTPD-LOGID: 624562847
RT: 624562847_d41d8cd98f00b204e9800998ecf8427e_d41d8cd98f00b204e9800998ecf8427e
Server: Apache1.0
SC: MISS.0.0
tracecode: 13487736192701306048062916
Set-Cookie: BAIDUID=8184D1B9CC4C45EB85C3AB62E8441688:FG=1; expires=Thu, 29-Jun-17 08:22:28 GMT; max-age=31536000; path=/; domain=.baidu.com; version=1
P3P: CP=" OTI DSP COR IVA OUR IND COM "{"song_list":[{"artist_id":"247010469","language":"\u56fd\u8bed","pic_big":"http:\/\/musicdata.baidu.com\/data2\/pic\/0c87cb20fd6b543cd1c90d1d82f1f6c5\/266782982\/266782982.jpg","pic_small":"http:\/\/musicdata.baidu.com\/data2\/pic\/169cbb0d82522568dea198363f7028ec\/266782985\/266782985.jpg","country":"\u5185\u5730","area":"0","publishtime":"2016-06-20","album_no":"1","lrclink":"http:\/\/musicdata.baidu.com\/data2\/lrc\/1f75306d7f1e25f723d3d175f5ef3d46\/266791084\/266791084.lrc","copy_type":"1","hot":"276927","all_artist_ting_uid":"232954914","resource_type":"0","is_new":"1","rank_change":"0","rank":"1","all_artist_id":"247010469","style":"\u6d41\u884c","del_status":"0","relate_status":"0","toneid":"0","all_rate":"64,128,256","sound_effect":"0","file_duration":0,"has_mv_mobile":1,"versions":"","bitrate_fee":"{\"0\":\"0|0\",\"1\":\"-1|-1\"}","song_id":"266784254","title":"\u7ea2","ting_uid":"232954914","author":"\u51af\u5efa\u5b87","album_id":"266784256","album_title":"\u7ea2","is_first_publish":0,"havehigh":0,"charge":0,"has_mv":1,"learn":0,"song_source":"web","piao_id":"0","korean_bb_song":"1","resource_type_ext":"1","mv_provider":"0100000000","artist_name":"\u51af\u5efa\u5b87"}],"billboard":{"billboard_type":"1","billboard_no":"1871","update_date":"2016-06-28","billboard_songnum":"190","havemore":1,"name":"\u65b0\u6b4c\u699c","comment":"\u8be5\u699c\u5355\u662f\u6839\u636e\u767e\u5ea6\u97f3\u4e50\u5e73\u53f0\u6b4c\u66f2\u6bcf\u65e5\u64ad\u653e\u91cf\u81ea\u52a8\u751f\u6210\u7684\u6570\u636e\u699c\u5355\uff0c\u7edf\u8ba1\u8303\u56f4\u4e3a\u8fd1\u671f\u53d1\u884c\u7684\u6b4c\u66f2\uff0c\u6bcf\u65e5\u66f4\u65b0\u4e00\u6b21","pic_s640":"http:\/\/c.hiphotos.baidu.com\/ting\/pic\/item\/f7246b600c33874495c4d089530fd9f9d62aa0c6.jpg","pic_s444":"http:\/\/d.hiphotos.baidu.com\/ting\/pic\/item\/78310a55b319ebc4845c84eb8026cffc1e17169f.jpg","pic_s260":"http:\/\/b.hiphotos.baidu.com\/ting\/pic\/item\/e850352ac65c1038cb0f3cb0b0119313b07e894b.jpg","pic_s210":"http:\/\/business.cdn.qianqian.com\/qianqian\/pic\/bos_client_c49310115801d43d42a98fdc357f6057.jpg","web_url":"http:\/\/music.baidu.com\/top\/new"},"error_code":22000}
打印成功。。。。
当然,该实现比较粗糙,仅作原理的解释
通过上面的实现,可以看到在
LoggingInterceptor
中可以获取到request
对象,那么我们可以通过设置其header()
,实现全局的request
头部信息的修改。
该博客中的源码已经共享到https://github.com/AlexSmille/alex_mahao_sample/tree/master/networklib,有需要请移步。
okhttp使用总结相关推荐
- 为什么要使用Retrofit封装OkHttp,而不单独使用OkHttp?
OkHttp的优点: 开源的轻量级框架.高效.快速的请求客户端,可以单独使用它来实现网络请求. 支持SPDY: 支持连接池,可极大减少延时: 支持Gzip压缩响应体,降低传输内容的大小: 支持Http ...
- HTTP 2.0与OkHttp
HTTP 2.0是对1.x的扩展而非替代,之所以是"2.0",是因为它改变了客户端与服务器之间交换数据的方式.HTTP 2.0增加了新的二进制分帧数据层,而这一层并不兼容之前的H ...
- 彻底理解OkHttp - OkHttp 源码解析及OkHttp的设计思想
OkHttp 现在统治了Android的网络请求领域,最常用的框架是:Retrofit+okhttp.OkHttp的实现原理和设计思想是必须要了解的,读懂和理解流行的框架也是程序员进阶的必经之路,代码 ...
- 再见,HttpClient!再见,Okhttp!
点击关注公众号,Java干货及时送达 作者:元人部落 来源:www.cnblogs.com/bryan31/p/13359376.html 1.背景 因为业务关系,要和许多不同第三方公司进行对接.这些 ...
- 我终于决定要放弃 okhttp、httpClient,选择了这个牛逼的神仙工具!贼爽!
点击上方蓝色"方志朋",选择"设为星标"回复"666"获取独家整理的学习资料! 在SpringBoot项目直接使用okhttp.httpCl ...
- 我终于决定要放弃 okhttp、httpClient,选择了这个牛逼的神仙工具!贼爽
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 在SpringBoot项目直接使用okhttp.httpC ...
- 扔掉okhttp、httpClient,来试试这款轻量级HTTP客户端神器?
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者: 伍陆七 juejin.cn/post/689848 ...
- HTTP客户端连接,选择HttpClient还是OkHttp?
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者: 何甜甜在吗 juejin.im/post/5e156c80 ...
- 一行代码实现Okhttp,Retrofit,Glide下载上传进度监听
2019独角兽企业重金招聘Python工程师标准>>> 发表上篇文章 我一行代码都不写实现Toolbar!你却还在封装BaseActivity? 已是一个月前的事情~ 上篇文章的研究 ...
- java accept encoding_Accept-Encoding gzip 乱码 和Okhttp的解决方法
在使用okhttp请求服务器数据的时候,发现返回的数据一直都是乱码,但是使用fiddler抓包,decode后,可以正常显示.刚开始一直怀疑是编码的问题,后来对比了hex的数据和程序中乱码的二进制,发 ...
最新文章
- 数据驱动安全需三大核心新技术
- 14,matlab中如何查看程序中所调用的函数
- 嵌入式软件工程师笔试题(含答案)
- 局部类的引用成员函数或虚函数必须进行定义
- 在做研究的时候很重要的事情
- rabbitmq java 应用实例
- 在UE中自由绘制基本图元的几种方法
- 1123. Is It a Complete AVL Tree (30)
- IDEA 自动生成 serialVersionUID 的设置
- CSU计算机图形学复习
- scala下载新的版本号
- 整体资产评估需要资料清单
- windows11 微信双开的方法
- PMP证书可以办北京工作居住证的消息,别说你还不知道!
- GitLab 安全漏洞 (CVE-2016-4340)复现
- 硕士研究生论文查重率多少合格?
- 【源代码】Python制作的赛车小游戏,逆行飙车
- 1.1 Java基础(一)概述
- 基于NETAPP实现内网穿透
- android xposed如何写,Android Xposed 模块与宿主App 配置读写
热门文章
- 【渝粤题库】陕西师范大学111118 商法学 作业
- QT实现图片的滚轮缩放、框选放大、拖拽移动
- int x=3,y=2;则表达式x+=x*=y+8的值为(60)
- 整理一些前端模版比较好的网站
- 物联网专业并不好_在广阔的物联网中,“智能”仍然并不意味着安全
- 2016年中山市信息学竞赛暨全国信息学联赛成绩表(普及组)
- 股票分时数据获取-东方财富
- Cesium火灾动画(模型动画,粒子特效)
- Wireshark数据包分析——Teardrop泪滴攻击
- 【史上最全】如何建立模型