OkHttp 也已经出来很久了,相信大家也都在项目中使用了,今天来对 OkHttp 使用进行一个简单的总结
一、概述
HTTP 是超文本传输协议,也是互联网上应用最为广泛的一种网络协议,高效的进行 HTTP 使用可以使你的东西更快的加载并节省带宽
OkHttp 是 HTTP 客户端的有效应用,OkHttp 处理了很多疑难杂症:
- 例如会从很多常用连接问题中自动恢复
- 如果你的服务器设置了多个 IP 地址,当第一个IP连接失败的时候,OkHttp 会自动尝试下一个 IP
- OkHttp 还处理了代理服务器问题和 SSL 握手失败问题
- 支持 HTTP/2,HTTP/2 通过使用多路复用技术在一个单独的 TCP 连接上支持并发,通过在一个连接上一次性发送多个请求来发送或接受数据
- 如果 HTTP/2 不可用,连接池复用技术也可以极大地减少延迟
使用 OkHttp 无需重写您程序中的网络代码,OkHttp 实现了几乎和 HttpURLConnection 一样的 API,OkHttp 支持 Android2.3 及以上
官网地址:http://square.github.io/okhttp/
GitHub 地址:https://github.com/square/okhttp
二、使用教程详解
首先使用前我们需要在 app 目录级别下的 build.gradle 中添加:
compile 'com.squareup.okhttp3:okhttp:3.8.1'
1. 异步 GET 请求
进行网络数据加载,想必第一个我们就得先来说 GET 请求,这里我们如果是新建的项目别忘了添加网络权限
<uses-permission android:name="android.permission.INTERNET" />
/**
* 异步Get请求
* @param view
*/
public void getRequest(View view) {
//创建 OkHttpClient 对象
OkHttpClient okHttpClient = new OkHttpClient();
//创建 Request
Request request = new Request.Builder()
.url("https://www.baidu.com/")
.build();
Call call = okHttpClient.newCall(request);
//发送请求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG, "失败------" + e.getLocalizedMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.e(TAG, "成功------" + response);
String result = response.body().string();
Log.e(TAG, result);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "请求成功", Toast.LENGTH_SHORT).show();
}
});
}
});
}
以上我们就完成了一个异步 Get 请求,首先创建了 Okhttp 对象,并构造了 Request 对象,并传入了一个 url,主意这里Request.Builder 还可以设置如 header、method 等的参数方法,然后通过 request 的对象去构造得到一个 Call 对象,最后我们调用Call 对象的 enqueue() 来执行,注意这里也可以选择同步 execute() 请求,将 call 加入到调度队列,然后等待执行完成,在 Callback 中得到回调结果,这里我们需要注意的就是,onResponse 回调的参数是 reponse,一般来说,如果我们希望获得返回的是字符串,可以通过 response.body().string() 获取,如果希望获得返回的二进制节数组,则通过 response.body().bytes() 等
2. 异步POST请求
/**
* 异步Post请求
*
* @param view
*/
public void postRequest(View view) {
//创建 OkHttpClient 对象
OkHttpClient okHttpClient = new OkHttpClient();
//构建 RequestBody
RequestBody formBody = new FormBody.Builder()
.add("键", "值")
.build();
//构建 Request
Request request = new Request.Builder()
.url("https://www.baidu.com/")
.post(formBody)
.build();
Call call = okHttpClient.newCall(request);
//发送请求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG, "失败------" + e.getLocalizedMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.e(TAG, "成功------" + response);
String result = response.body().string();
Log.e(TAG, result);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "请求成功", Toast.LENGTH_SHORT).show();
}
});
}
});
}
这里需要注意一下 OkHttp3 异步 POST 请求和 OkHttp2.x 有一点区别就是没有 FormEncodingBuilder 这个类,替代它的就是FormBody,大家都知道,post 的时候,参数是包含在请求体中的,所以我们通过 FormBody 来添加多个 String 键值对,然后去构造 RequestBody,来完成我们 Request 的构造,后面的步骤基本就和 get 请求一样了,还有就是这了提交的表单格式可以有多种
如果表单是 json:
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, "你的json");
如果数据包含文件:
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("image/png"), file))
.build();
接下来我们将会讲具体解到
3. 异步上传文件
定义上传文件得类型:
//上传文件的类型
public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");
/**
* 异步上传文件
*
* @param view
*/
public void postFile(View view) {
OkHttpClient okHttpClient = new OkHttpClient();
File file = new File("上传的文件");
Request request = new Request.Builder()
.url("上传的地址")
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN,file))
.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 {
}
});
}
这里也要注意不要忘记添加权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
可以看到上传文件其实也是一个 POST 请求
4. 异步上传 Multipart 文件
//定义类型
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
/**
* 异步上传Multipart文件
*/
public void sendMultipart() {
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", "nihao")
.addFormDataPart("image", "image.jpg", RequestBody.create(MEDIA_TYPE_PNG, new File("/sdcard/image.jpg")))
.build();
Request request = new Request.Builder()
.header("Authorization", "Client-ID " + "...")
.url("https://api.imgur.com/3/image")
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.i(TAG, response.body().string());
}
});
}
异步上传文件这种场景在开发中还是很常用的,上传不同类型的文件同时还需要传其他类型的字段,这些用 OkHttp3 实现起来很简单,这里我们只是做了一个示例,实际开发中大家还要具体对应自己的服务器联调
5. 异步下载文件
/**
* 异步下载文件
*
* @param view
*/
public void downFile(View view) {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url("下载地址").build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) {
InputStream inputStream = response.body().byteStream();
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(new File("/sdcard/iamge.jpg"));
byte[] buffer = new byte[2048];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, len);
}
fileOutputStream.flush();
} catch (IOException e) {
Log.i(TAG, "IOException");
e.printStackTrace();
}
Log.d(TAG, "文件下载成功");
}
});
}
6. 设置超时时间和缓存
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 okHttpClient=builder.build();
这里需要注意得是和 OkHttp2.x 不同的是,不能通过 OkHttpClient 直接设置超时和缓存了,而是通过 OkHttpClient.Builder 来设置,通过 builder 配置好 OkHttpClient 后用 builder.builder() 来返回 OkHttpClient
我们用到的大概也就这些了,都是一些比较基本的用法,在实际项目中,大家肯定还得进行进一步的封装,要不这样使用大家也看到了,怪累,今天就写到这里,有错误的地方请指出