支持 SPDY ,共享同一个 Socket 来处理同一个服务器的所有请求
1、如果 SPDY 不可用,则通过连接池来减少请求延时
2、无缝的支持GZIP来减少数据流量
3、缓存响应数据来减少重复的网络请求
OkHttp 处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(requestUrl)
.build();
requestUrl是一个字符串变量,表示这个URL是为了JSON请求(The requestUrl is a String variable representing the Url for the JSON request.)
在这个测试中,我们将会使用如下的URl:http://iheartquotes.com/api/v1/random?format=json
Call call = okHttpClient.newCall(request);
Call对象会取走我们的 okHttpClient对象 和 我们的 request对象。
并且会抛出一个 IOException的异常,这就是为什么们会用一个try,catch块包裹她。
try{
Response response = call.execute();
}catch (IOException e){
e.printStackTrace();
}
通过response.isSuccessful()的返回值为true或者是false来判断。
这我们仅仅是一个测试,如果Call成功的话,我们将会通过Log来打印我们的response。
try{
Response response = call.execute();
if(response.isSuccessful()){
//The call was successful.print it to the log
Log.v("OKHttp",response.body().string());
}
}catch(IOException e){
e.printStackTrace();
}
这是新手一个常见的错误。在Android中不允许任何网络的交互在主线程中进行。
It disallows it to force developers to use asynchronous callbacks.
但是现在,我们的代码看起来看起来十分的号好!下面我们来看看如何修复这个问题。
为了修补这个问题,我们只需要让我们的Call执行在非主线程内,
所以利用一个 asynchronous callback(异步的callBack)。
让我们call异步的方法是通过调用我们Call对象的 enqueue()方法。
call.enqueue(new Callback()) {
@Override
public void onFailure( Request request, IOException e ) {
}
@Override
public void OnResponse( Response response) throws IOException {
try {
if(response.isSuccessful()){
//The call was successful. print it to the log
log.v("OKHttp",response.body.string());
}
}catch (IOException e) {
e.printStackTrace();
}
}
});
因为我们应用的程序没有得到相应的相应的网络权限。所以我们需要再AndroidManifest.xml中添加应用权限。
<uses-permission android:name="android.permission.INTERNET"/>
This means, we are now able to execute asynchronous network calls and use the data inside the callback method, when it is ready!
onResponse回调的参数是response,一般情况下,
比如我们希望获得返回的字符串,可以通过response.body().string()获取;
如果希望获得返回的二进制字节数组,则调用response.body().bytes();
如果你想拿到返回的inputStream,则调用response.body().byteStream()
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());
}
Response类的string()方法会把文档的所有内容加载到内存,适用于小文档,
对应大于1M的文档,应使用流()的方式获取。
response.body().byteStream()
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, IOException e) {
e.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());
}
});
}
读取响应会阻塞当前线程,所以发起请求是在主线程,回调的内容在非主线程中。
private 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());
}
因为整个请求体都在内存中,应避免提交1M以上的文件。
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
RequestBody requestBody = new RequestBody() {
@Override
public MediaType contentType() {
return MEDIA_TYPE_MARKDOWN;
}
@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());
}
使用Okio框架以流的形式将内容写入,这种方式不会出现内存溢出问题。
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());
}
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());
}
表单的每个Names-Values都进行了URL编码。如果服务器端接口未进行URL编码,可定制个 FormBuilder。
private static final String IMGUR_CLIENT_ID = "...";
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
// Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"title\""),
RequestBody.create(null, "Square Logo"))
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"image\""),
RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))
.build();
Request request = new Request.Builder()
.header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
.url("https://api.imgur.com/3/image")
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful())
throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
参考文献
http://blog.csdn.net/liyuchong2537631/article/details/48369403