前言:OkHttp是Square开发的第三方库,用于发送和接收基于HTTP的网络请求。它建立在Okio库之上,通过创建共享内存池,它尝试通过标准Java I / O库更高效地读取和写入数据。它还是Retrofit库的底层库,为使用基于REST的API提供类型安全性。Square公司是不是看着很 眼红 (眼熟),是的没错,这家公司在开源的道路上做足了贡献,造福了无数程序员。除了OkHttp外,还有Picasso、Retrofit、otto等著名的开源项目。目前OkHttp最新版本是3.x,支持Android 2.3+,所以以下所讲内容都是基于OkHttp3.x。
OkHttp项目开源地址 :https://github.com/square/okhttp
基本使用
●配置与导入
在AndroidManifest.xml文件中打开了联网的权限:
在Android Studio 中配置gradle:
compile 'com.squareup.okhttp3:okhttp:3.5.0'
●发送和接收网络请求
实例化一个OkHttpClient并创建一个Request对象。
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
如果有任何需要添加的查询参数,OkHttp提供的HttpUrl类可以用来构造URL:
HttpUrl.Builder urlBuilder = HttpUrl.parse("http://blog.csdn.net/donkor_").newBuilder();
//addQueryParameter 添加查询参数
urlBuilder.addQueryParameter("name", "donkor");
urlBuilder.addQueryParameter("blog", "okhttp3");
urlBuilder.addQueryParameter("number", "8");
String url = urlBuilder.build().toString();
Request request = new Request.Builder()
.url(url)
.build();
●同步Get
因为Android不允许主线程上的网络调用,所以只能在单独的线程或后台服务上进行同步调用。
new Thread(new Runnable() {
@Override
public void run() {
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
//newCall方法会得到一个Call对象,表示一个新的网络请求
//execute方法是同步方法,会阻塞当前线程,并返回Response对象
okhttp3.Response response = client.newCall(request).execute();
String data=response.body().string();
if (response.isSuccessful()) {
Log.e("asd","okHttp is request success");
} else {
Log.e("asd", "okHttp is request error");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
※ 注
:通过Response对象的body()方法可以得到响应体ResponseBody对象,调用其string()方法可以很方便地将响应体中的数据转换为字符串,该方法会将所有的数据放入到内存之中,所以如果数据超过1M,最好不要调用string()方法以避免占用过多内存,这种情况下可以考虑将数据当做Stream流处理。
●异步Get
//enqueue方法调用异步请求网络,该方法接收一个okhttp3.Callback对象,
// 且不会阻塞当前线程,会新开一个工作线程,让实际的网络请求在工作线程中执行。
//当异步请求成功后,会回调Callback对象的onResponse方法,在该方法中可以获取Response对象。
// 当异步请求失败或者调用了Call对象的cancel方法时,会回调Callback对象的onFailure方法。
// onResponse和onFailure这两个方法都是在工作线程中执行的。
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("asd", "okHttp is request erro");
Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.e("asd", "okHttp is request success");
String data=response.body().string();
//在主线程中进行UI修改操作
runOnUiThread(new Runnable() {
@Override
public void run() {
//do something
}
});
}
});
●Post方式发送String
使用HTTP POST提交请求到服务。这个例子提交了一个markdown文档到web服务,以HTML方式渲染markdown。因为请求体会放置在内存中,所以应该避免用该API发送超过1M的数据。
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";
//post方法接收一个RequestBody对象
//create方法第一个参数都是MediaType类型,create方法的第二个参数可以是String、File、byte[]或okio.ByteString
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方式发送Stream流
这里我们将请求主体作为流。 请求体的内容由流写入产生。 此示例直接流入Okio缓冲接收器。 您的程序可能更喜欢OutputStream,您可以从BufferedSink.outputStream()获取。
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 {
RequestBody requestBody = new RequestBody() {
//重写contentType()方法,返回markdown类型的MediaType
@Override public MediaType contentType() {
return MEDIA_TYPE_MARKDOWN;
}
//重写writeTo()方法,该方法会传入一个Okia的BufferedSink类型的对象,
//可以通过BufferedSink的各种write方法向其写入各种类型的数据,
//此例中用其writeUtf8方法向其中写入UTF-8的文本数据。
//也可以通过它的outputStream()方法,得到输出流OutputStream,
//从而通过OutputSteram向BufferedSink写入数据。
@Override public void writeTo(BufferedSink sink) throws IOException {
sink.writeUtf8("Numbers\n");
sink.writeUtf8("-------\n");
for (int i = 2; i <= 997; i++) {
sink.writeUtf8(String.format(" * %s = %s\n", i, factor(i)));
}
}
private String factor(int n) {
for (int i = 2; i < n; i++) {
int x = n / i;
if (x * i == n) return factor(x) + " × " + i;
}
return Integer.toString(n);
}
};
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
●POST方式发送文件File
上传文件在实际开发中也经常用到,这里比较简单,直接看代码:
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 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方式Form表单中的键值对
使用FormBody.Builder来构建类似于HTML