前言
废话不多说,先奉上
OkHttp GitHub
说到OKHTTP,我想你肯定不会陌生,Android中无数大大小小的项目在用这个开源库,甚至包括Google开发的一些项目也在用。Android API23 抛弃了httpclient之后,我想肯定会有很多人在为寻找下一个好用的网络库而犯愁。看到这里,我认为你走对了。
OkHttp使用的几种方式
OkHttp的性能我自不必说,关于使用方式(异步GET,同步GET...)自不必说,网上资料非常多。在这里我直接贴出代码。
同步get
下载一个文件,打印他的响应头,以string形式打印响应体。
响应体的 string() 方法对于小文档来说十分方便、高效。但是如果响应体太大(超过1MB),应避免适应 string()方法 ,因为他会将把整个文档加载到内存中。对于超过1MB的响应body,应使用流的方式来处理body。
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + 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());
}
异步get
在一个工作线程中下载文件,当响应可读时回调Callback接口。读取响应时会阻塞当前线程。OkHttp现阶段不提供异步api来接收响应体。
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build();
client.newCall(request).enqueue(new Callback() {
@Override public void onFailure(Request request, Throwable throwable) {
throwable.printStackTrace();
}
@Override public void onResponse(Response response) throws IOException {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + 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());
}
});
}
Post方式提交String
使用HTTP POST提交请求到服务。这个例子提交了一个markdown文档到web服务,以HTML方式渲染markdown。因为整个请求体都在内存中,因此避免使用此api提交大文档(大于1MB)。
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
String postBody = ""
+ "Releases\n"
+ "--------\n"
+ "\n"
+ " * _1.0_ May 6, 2013\n"
+ " * _1.1_ June 15, 2013\n"
+ " * _1.2_ August 11, 2013\n";
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody))
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
Post方式提交文件
直接封装好文件体就可以
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
File file = new File("README.md");
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
Post方式提交表单
估计这是一种最常用的方式了
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
RequestBody formBody = new FormEncodingBuilder()
.add("search", "Jurassic Park")
.build();
Request request = new Request.Builder()
.url("https://en.wikipedia.org/w/index.php")
.post(formBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
缓存策略
我当初在这方面卡了一些时间。这也是今天的重点。
<code>
File httpCacheDirectory = new File(pActivity.getExternalCacheDir(), "cache_zhiyixing");
</code>
首先创建文件缓存目录,这里有两个参数
new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.cache(new Cache(httpCacheDirectory, 1024 * 1024 * 10)).build();
通过OKHTTP的构建者模式把文件目录传入进去。运行之后,从外置存储中你会发现缓存目录已经创建完成。而且内容也已经缓存进去了。
断网,再次打开软件,发现并不能把缓存读取出来。
这是为什么呢?
这是OKHTTP的缓存策略导致的。用户可以设置cache-control来控制缓存的时效。有关cache-control的介绍请戳这里,不能翻墙的戳这里
这里我把配置代码放上
package com.android.zhixing.model;
import android.content.Context;
import com.android.zhixing.utils.NetWorkUtils;
import com.socks.library.KLog;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/**
* Created by dengqiangxi on 16/5/30.
*/
public class OurOkHttpClient {
public static OkHttpClient getClient(final Context pActivity) {
File httpCacheDirectory = new File(pActivity.getExternalCacheDir(), "cache_zhiyixing");
return new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.cache(new Cache(httpCacheDirectory, 1024 * 1024 * 10))
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Log.e("新请求", "=request==" + request.toString());
Response response = chain.proceed(request);
if (NetWorkUtils.isNetworkReachable(pActivity)) {
int maxAge = 60 * 60*24; // 有网络的时候从缓存1天后失效
response.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", "public, max-age=" + maxAge)
.build();
} else {
int maxStale = 60 * 60 * 24 * 28; // // 无网络缓存保存四周
response.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.build();
}
return response;
}
})
.build();
}
}
至此,有关OKHTTP的相关配置就已经介绍完了,下一节将介绍OKHTTP和retrofit结合使用。