概述
OkHttp是一款优秀的HTTP框架,它支持get请求和post请求,支持基于Http的文件上传和下载,支持加载图片,支持下载文件透明的GZIP压缩,支持响应缓存避免重复的网络请求,支持使用连接池来降低响应延迟问题。
OkHttp官网地址:http://square.github.io/okhttp/
OkHttp GitHub地址:https://github.com/square/okhttp
使用介绍
1.使用前的准备工作
配置gradle
在AndroidStudio中使用不需要下载jar包,直接添加依赖即可:
compile 'com.squareup.okhttp3:okhttp:3.10.0'
2.GET异步请求
这种方式的好处是不用开启子线程,但是回调方法是在子线程中,所以更新UI还是要在子线程中,示例代码如下:
//1.拿到OkHttpClient的对象
OkHttpClient okHttpClient=new OkHttpClient();
//2.构造Request
Request request=new Request.Builder().get().url("https://blog.csdn.net/wen_haha").build();
//3.将Request封装为Call
//4.执行call
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String result = response.body().string();
L.e(result);
runOnUiThread(new Runnable() {
@Override
public void run() {
mTvGetResult.setText(result);
}
});
}
});
其基本步骤就是创建OkHttpClient、Request和Call,最后调用Call的enqueue()方法。如果想要调用同步GET请求,可以调用Call的execute方法。
3.异步POST请求
OkHttp3异步POST请求和OkHtto2.x有一些区别,就是没有FormEncodingBuilder这个类,替代它的是功能更强大的FormBody。我这里访问是我自己写的服务端,示例代码如下:
Request.Builder builder=new Request.Builder();
//构造RequestBody
RequestBody formBody=new FormBody.Builder().add("username", "jwj").add("password", "123").build();
Request request = builder.url(mUrl + "login").post(formBody).build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String result = response.body().string();
L.e(result);
runOnUiThread(new Runnable() {
@Override
public void run() {
mTvGetResult.setText(result);
}
});
}
});
异步POST请求和异步GET请求很类似,只是多了用FormBody来封装请求的参数,并传递给Request
4.异步上传文件
上传文件本身也是一个POST,在上传之前需要定义上传文件的类型。示例代码如下:
File file=new File(Environment.getExternalStorageDirectory(),"123456.txt");
L.e(file.getAbsolutePath().toString());
if (!file.exists()){
L.e("不存在!");
return;
}
//application/octet-stream
RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
Request.Builder builder=new Request.Builder();
Request request = builder.url(mUrl + "postFile").post(requestBody).build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String result = response.body().string();
L.e(result);
runOnUiThread(new Runnable() {
@Override
public void run() {
mTvGetResult.setText(result);
}
});
}
});
注意:上传文件涉及到权限问题,在6.0以后需要手动开启运行权限,不明白的可以去看我的关于运行权限的那篇博客。
MediaType.parse()就是定义文件类型,如果不知道怎么写,可以去http://www.w3school.com.cn/media/media_mimeref.asp查一下。如果想要改成同步上传文件,只要调用OkHttpClient.newCall(request).execute()就可以了。
5.异步下载文件
在OKHttp中并没有提供下载文件的功能,但是在Response中可以获取流对象,有了流对象我们就可以自己实现文件的下载。这段代码需要写在onResponse()中,示例代码如下:
OkHttpClient okHttpClient=new OkHttpClient();
Request request=new Request.Builder().get().url("http://img.lanrentuku.com/img/allimg/1707/14988864745279.jpg").build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
InputStream is = response.body().byteStream();
final Bitmap bitmap = BitmapFactory.decodeStream(is);
runOnUiThread(new Runnable() {
@Override
public void run() {
mIvPhoto.setImageBitmap(bitmap);
}
});
}
});
我这是通过Get请求下载了网络上的一张照片,并没有通过裁剪压缩,直接就展示在ImageView中,但在真实的项目中,如果图片过大,可能要经过裁剪,压缩。
6.异步上传Multipart文件
上传文件的时候,有时候还需要上传其他类型的字段,OkHttp通过MultipartBody来实现,示例代码如下:
File file=new File(Environment.getExternalStorageDirectory(),"123456.png");
L.e(file.getAbsolutePath().toString());
if (!file.exists()){
L.e("不存在!");
return;
}
MultipartBody.Builder multipartBuilder=new MultipartBody.Builder();
RequestBody requestBody= multipartBuilder.setType(MultipartBody.FORM)
.addFormDataPart("username", "jwj")//1
.addFormDataPart("password", "123456")
.addFormDataPart("mPhoto", "jwj.png", RequestBody.create(MediaType.parse("application/octet-stream"), file))//2
.build();
CountingRequestBody countingRequestBody=new CountingRequestBody(requestBody, new CountingRequestBody.Listener() {
@Override
public void onRequestProgress(long byteWrited, long contentLength) {
L.e(byteWrited+"/"+contentLength);
}
});
Request.Builder builder=new Request.Builder();
Request request = builder.url(mUrl + "upLoadInfo").post(countingRequestBody).build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String result = response.body().string();
L.e(result);
}
});
首先我们要定义上传文件的类型。上面注释1是我们常见的key-value形式的参数上传,注释2则是上传表单。addFormDataPart方法的第一个参数是key值,第二个参数是上传文件的名字,第三个参数是需要上传的文件。
7.取消请求
使用call.cancel()可以立即停止一个正在执行的call,不管同步还是异步的call都可以取消,也可以通过tag来同时取消多个请求。示例代码如下:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
final Request request = new Request.Builder()
.url("http://www.baidu.com")
.cacheControl(CacheControl.FORCE_NETWORK)
.build();
Call call = null;
call = okHttpClient.newCall(request);
final Call finalCall = call;
//100毫秒后取消call
executor.schedule(new Runnable() {
@Override
public void run() {
finalCall.cancel();
}
}, 1, TimeUnit.MILLISECONDS);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (null != response.cacheResponse()) {
String str = response.cacheResponse().toString();
L.e("cache---" + str);
} else {
String str = response.networkResponse().toString();
L.e("network---" + str);
}
}
});
9.设置超时时间和缓存
OkHttp3可以通过OkHttpClient.Builder来设置超时时间和缓存。通过builder配置好OkHttpClient后用builder.build()来返回OkHttpClient。示例代码如下:
File sdcache = getExternalCacheDir();
int cacheSize = 10 * 1024 * 1024;
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.cache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
okHttpClient = builder.build();
总结:
OkHttp的简单使用就已经说完了,但是如果每次都请求网络都需要写重复的代码,有时候我们需要对OkHttp进行封装一下,使OkHttp能够更加方便的使用,更加具有拓展性。我们下一篇博客就来讲解一下OkHttp的封装。
Demo
CSDN:https://download.csdn.net/download/wen_haha/10540745
Github:https://github.com/kongkongdaren/OkHttpDemo