OkHttp官网地址:http://square.github.io/okhttp/
OkHttp GitHub地址:https://github.com/square/okhttp
OkHttp文档:http://square.github.io/okhttp/3.x/okhttp/
OkHttp是一个处理网络请求的开源项目,是安卓端一个很火热的轻量级网络框架,由Square公司贡献(该公司还贡献了Picasso),用于替代HttpUrlConnection和Apache HttpClient(而且我们都知道,在Android API23,也就是Android 6.0里面已经移除了HttpClient的一些API)。
OkHttp优势:
① 共享Socket,减少对服务器的请求次数;
② 通过连接池,减少了请求延迟;
③ 支持GZIP来减少数据流量;
④ 缓存响应数据来减少完全重复的网络请求;
⑤ 使用 OkHttp 无需重写您程序中的网络代码。OkHttp实现了几乎和java.net.HttpURLConnection一样的API;
⑥ OkHttp会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,会自动尝试下一个IP。
添加依赖:
在Android Studio中使用OkHttp需要在build.gradle中添加依赖(okhttp内部依赖okio,所以需要同时添加依赖):
dependencies {
...
compile 'com.squareup.okhttp3:okhttp:3.6.0'
compile 'com.squareup.okio:okio:1.11.0'
}
在Eclipse中使用的话,需要取官网或者GitHub上下载在导入到项目中。
OkHttp的使用:
(注意:以下代码使用的是版本是 okhttp:3.6.0、okio:1.11.0,不同的版本可能会有细微差别)
1.Get请求数据(同步和异步)
① OkHttp使用GET方式同步请求数据:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
try {
Response response = client.newCall(request).execute();
String result = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
在使用同步请求的时候,需要注意在主线程中是不可以访问网络的。
② OkHttp使用GET方式异步请求数据:
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) {
// 请求失败时的回调
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// 请求成功时的回调
}
});
在使用异步请求的时候是通过回调的形式将请求结果或者错误信息进行传递。
在使用POST请求提交数据的时候,同样可以使用同步和异步的形式,在下面的几个示例中,为了节省空间减少篇幅,所以都是用的是同步的形式,如果想使用异步的话,和上面的GET一样,不调用execute()方法,而调用enqueue(Callback responseCallback)方法就可以了。
2.POST请求提交表单数据(key-value形式)
OkHttpClient client = new OkHttpClient();
RequestBody formBody = new FormBody.Builder()
.add("search", "Jurassic Park")
//.addEncoded("key", "value");
.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
try {
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
String result = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
3.POST请求提交(JSON/String/文件等)
① 使用OkHttp POST方式上传JSON类型的数据:
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(JSON, json数据);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try {
Response response = client.newCall(request).execute();
String result = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
② 使用OkHttp POST方式上传String类型的数据:
private static final MediaType STRING = MediaType.parse("text/plain; charset=utf-8");
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(STRING, String数据);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try {
Response response = client.newCall(request).execute();
String result = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
③ 使用OkHttp POST方式上传文件:
File file = new File("file path"); // 需要上传的文件
OkHttpClient client = new OkHttpClient();
MultipartBody multipartBody = new MultipartBody.Builder()
.addFormDataPart("name", "value") // 普通键值对参数
// 需要上传的文件,文件的 MediaType 可以通过 URLConnection.getFileNameMap().getContentTypeFor(fileName) 获取
.addFormDataPart("param_name", "filename", RequestBody.create(MediaType.parse("文件MediaType"), file))
.build();
Request request = new Request.Builder()
.url(url)
.post(multipartBody)
.build();
try {
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
String result = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
// 根据文件名获取文件的 MIME 类型:
private String getFileMime(String fileName) {
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String contentTypeFor = fileNameMap.getContentTypeFor(fileName);
if (null == contentTypeFor) {
return "application/octet-stream";
}
return contentTypeFor;
}
4.文件下载
文件下载其实和普通的请求一样,只是我们普通请求在解析response的时候是通过string()方法获取String类型的数据,在下载文件的时候,通过byteStream()方法获取到InputStream对象,然后将InputStream中的数据保存成File就可以了。
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) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// 通过 response.body().byteStream() 获取 InputStream 对象
InputStream inputStream = response.body().byteStream();
// 定义文件保存路径
FileOutputStream fileOutputStream = new FileOutputStream(new File("文件保存路径"));
byte[] buffer = new byte[2048];
int len;
while ((len = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, len);
}
fileOutputStream.flush();
Log.d("OkHttp Download File", "文件下载成功...");
}
});
5.取消请求
// 使用线程池
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
final Call call = client.newCall(request);
executor.schedule(new Runnable() {
@Override
public void run() {
// 取消请求
call.cancel();
}
}, 1, TimeUnit.SECONDS); // 延迟 1秒 执行
try (Response response = call.execute()) {
Log.i("Response Result", "response : " + response);
} catch (IOException e) {
Log.e("Exception Info","IOException : " + e);
e.printStackTrace();
}
6.对OkHttoClient进行配置
int cacheSize = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(cacheDirectory, cacheSize);
OkHttpClient client = new OkHttpClient.Builder()
// 设置缓存目录和大小
.cache(cache)
// 设置超时时间
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10,TimeUnit.SECONDS)
.writeTimeout(10,TimeUnit.SECONDS)
// 设置连接池
.connectionPool(new ConnectionPool(5,30,TimeUnit.MINUTES))
// 还可以设置 拦截器、DNS等
.build();
OkHttp的一些使用就介绍到这里了。看了上面的代码,如果每次我们使用都去创建一个OkHttpClient的话,肯定是没有必要也是不推荐的做法,所以我们可以对OkHttp做进一步的封装。我已经对OkHttp做了一个简单的封装,包括请求数据、提交数据、取消请求以及带进度条的上传和下载文件,下载优快云代码 Github代码下载。