现在android网络方面的第三方库很多,volley,Retrofit,OKHttp等,各有各自的特点,这边博客就来简单介绍下如何使用OKHttp。

梗概

OKHttp是一款高效的HTTP客户端,支持连接同一地址的链接共享同一个socket,通过连接池来减小响应延迟,还有透明的GZIP压缩,请求缓存等优势OKHttp官网

配置环境

支持Android 2.3及其以上版本,要求java JDK1.7以上

jar包引入

可以通过下载jar包直接导入工程地址如下下载地址 
或者通过构建的方式导入 
MAVEN:

<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp</artifactId>
<version>2.4.0</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

GRADLE

compile 'com.squareup.okhttp:okhttp:2.4.0'
  • 1

用法

在向网络发起请求的时候,我们最常用的就是GET和POST,下面就来看看如何使用 
1. GET 
在OKHttp,每次网络请求就是一个Request,我们在Request里填写我们需要的url,header等其他参数,再通过Request构造出Call,Call内部去请求参数,得到回复,并将结果告诉调用者。

package com.jackchan.test.okhttptest;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log; import com.squareup.okhttp.Cache;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response; import java.io.File;
import java.io.IOException; public class TestActivity extends ActionBarActivity { private final static String TAG = "TestActivity"; private final OkHttpClient client = new OkHttpClient(); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
new Thread(new Runnable() {
@Override
public void run() {
try {
execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
} public void execute() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build();
Response response = client.newCall(request).execute();
if(response.isSuccessful()){
System.out.println(response.code());
System.out.println(response.body().string());
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

我们通过Request.Builder传入url,然后直接execute执行得到Response,通过Response可以得到code,message等信息。

这个是通过同步的方式去操作网络请求,而android本身是不允许在UI线程做网络请求操作的,因此我们需要自己开启一个线程。

当然,OKHttp也支持异步线程并且有回调返回,有了上面同步的基础,异步只要稍加改动即可

private void enqueue(){
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) { } @Override
public void onResponse(Response response) throws IOException {
//NOT UI Thread
if(response.isSuccessful()){
System.out.println(response.code());
System.out.println(response.body().string());
}
}
});
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

就是在同步的基础上讲execute改成enqueue,并且传入回调接口,但接口回调回来的代码是在非UI线程的,因此如果有更新UI的操作记得用Handler或者其他方式。

2、POST

说完GET该介绍些如何使用POST,POST情况下我们一般需要传入参数,甚至一些header,传入参数或者header 
比如传入header 
Request request = new Request.Builder() 
.url("https://api.github.com/repos/square/okhttp/issues") 
.header("User-Agent", "OkHttp Headers.java") 
.addHeader("Accept", "application/json; q=0.5") 
.addHeader("Accept", "application/vnd.github.v3+json") 
.build();
 
传入POST参数

RequestBody formBody = new FormEncodingBuilder()
.add("platform", "android")
.add("name", "bug")
.add("subject", "XXXXXXXXXXXXXXX")
.build(); Request request = new Request.Builder()
.url(url)
.post(body)
.build();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

可以看出来,传入header或者post参数都是传到Request里面,因此最后的调用方式也和GET方式一样

Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这个代码是同步网络请求,异步就改成enqueue就行了。

请求缓存

在网络请求中,缓存技术是一项应用比较广泛的技术,需要对请求过的网络资源进行缓存,而okhttp也支持这一技术,也使用十分方便,前文涨经常出现的OkHttpclient这个时候就要派送用场了。看下面代码

package com.jackchan.test.okhttptest;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log; import com.squareup.okhttp.Cache;
import com.squareup.okhttp.CacheControl;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response; import java.io.File;
import java.io.IOException; public class TestActivity extends ActionBarActivity { private final static String TAG = "TestActivity"; private final OkHttpClient client = new OkHttpClient(); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
File sdcache = getExternalCacheDir();
int cacheSize = 10 * 1024 * 1024; // 10 MiB
client.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
new Thread(new Runnable() {
@Override
public void run() {
try {
execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
} public void execute() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build(); Response response1 = client.newCall(request).execute();
if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1); String response1Body = response1.body().string();
System.out.println("Response 1 response: " + response1);
System.out.println("Response 1 cache response: " + response1.cacheResponse());
System.out.println("Response 1 network response: " + response1.networkResponse()); Response response2 = client.newCall(request).execute();
if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2); String response2Body = response2.body().string();
System.out.println("Response 2 response: " + response2);
System.out.println("Response 2 cache response: " + response2.cacheResponse());
System.out.println("Response 2 network response: " + response2.networkResponse()); System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body)); }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68

okhttpclient有点像Application的概念,统筹着整个okhttp的大功能,通过它设置缓存目录,我们执行上面的代码,得到的结果如下 
 
response1 的结果在networkresponse,代表是从网络请求加载过来的,而response2的networkresponse 就为null,而cacheresponse有数据,因为我设置了缓存因此第二次请求时发现缓存里有就不再去走网络请求了。 
但有时候即使在有缓存的情况下我们依然需要去后台请求最新的资源(比如资源更新了)这个时候可以使用强制走网络来要求必须请求网络数据

 public void execute() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build(); Response response1 = client.newCall(request).execute();
if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1); String response1Body = response1.body().string();
System.out.println("Response 1 response: " + response1);
System.out.println("Response 1 cache response: " + response1.cacheResponse());
System.out.println("Response 1 network response: " + response1.networkResponse()); request = request.newBuilder().cacheControl(CacheControl.FORCE_NETWORK).build();
Response response2 = client.newCall(request).execute();
if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2); String response2Body = response2.body().string();
System.out.println("Response 2 response: " + response2);
System.out.println("Response 2 cache response: " + response2.cacheResponse());
System.out.println("Response 2 network response: " + response2.networkResponse()); System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body)); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

上面的代码中 
response2对应的request变成

request = request.newBuilder().cacheControl(CacheControl.FORCE_NETWORK).build();
  • 1

我们看看运行结果 
 
response2的cache response为null,network response依然有数据。

同样的我们可以使用 FORCE_CACHE 强制只要使用缓存的数据,但如果请求必须从网络获取才有数据,但又使用了FORCE_CACHE 策略就会返回504错误,代码如下,我们去okhttpclient的缓存,并设置request为FORCE_CACHE

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
File sdcache = getExternalCacheDir();
int cacheSize = 10 * 1024 * 1024; // 10 MiB
//client.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
new Thread(new Runnable() {
@Override
public void run() {
try {
execute();
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage().toString());
}
}
}).start();
} public void execute() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build(); Response response1 = client.newCall(request).execute();
if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1); String response1Body = response1.body().string();
System.out.println("Response 1 response: " + response1);
System.out.println("Response 1 cache response: " + response1.cacheResponse());
System.out.println("Response 1 network response: " + response1.networkResponse()); request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();
Response response2 = client.newCall(request).execute();
if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2); String response2Body = response2.body().string();
System.out.println("Response 2 response: " + response2);
System.out.println("Response 2 cache response: " + response2.cacheResponse());
System.out.println("Response 2 network response: " + response2.networkResponse()); System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body)); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

取消操作

网络操作中,经常会使用到对请求的cancel操作,okhttp的也提供了这方面的接口,call的cancel操作。使用Call.cancel()可以立即停止掉一个正在执行的call。如果一个线程正在写请求或者读响应,将会引发IOException,同时可以通过Request.Builder.tag(Object tag)给请求设置一个标签,并使用OkHttpClient.cancel(Object tag)来取消所有带有这个tag的call。但如果该请求已经在做读写操作的时候,cancel是无法成功的,会抛出IOException异常。

public void canceltest() throws Exception {
Request request = new Request.Builder()
.url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay.
.build(); final long startNanos = System.nanoTime();
final Call call = client.newCall(request); // Schedule a job to cancel the call in 1 second.
executor.schedule(new Runnable() {
@Override
public void run() {
System.out.printf("%.2f Canceling call.%n", (System.nanoTime() - startNanos) / 1e9f);
call.cancel();
System.out.printf("%.2f Canceled call.%n", (System.nanoTime() - startNanos) / 1e9f);
}
}, 1, TimeUnit.SECONDS); try {
System.out.printf("%.2f Executing call.%n", (System.nanoTime() - startNanos) / 1e9f);
Response response = call.execute();
System.out.printf("call is cancel:" + call.isCanceled() + "%n");
System.out.printf("%.2f Call was expected to fail, but completed: %s%n",
(System.nanoTime() - startNanos) / 1e9f, response);
} catch (IOException e) {
System.out.printf("%.2f Call failed as expected: %s%n",
(System.nanoTime() - startNanos) / 1e9f, e);
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

成功取消 

取消失败

简单的对于OKHttp的使用就介绍到这里,下次将重点从源码角度介绍整个OKHttp是如何运转的。

OKHttp使用简介的更多相关文章

  1. okhttp的简介(二)之简单封装

    前一篇文章简单的介绍了okhttp的简单使用.okhttp的简介(一):http://blog.csdn.net/wuyinlei/article/details/50579564 相信使用还是非常好 ...

  2. Okhttp【简介】应用 示例

    资源 GitHub:https://github.com/square/okhttp 官网     文档     API  You'll also need Okio[https://github.c ...

  3. 开源框架相关面试问题-okhttp网络框架面试问题详解

    OkHttp使用简介: ①.准备OkHttpClient对象: 一般app中使用网络可以全部用它,可以将它弄为全局变量,这样就可以共用它的缓存和线程池了. ②.准备Request对象: 很显然它是采用 ...

  4. OkHttp简介

    什么是OKHttp 一般在Java平台上,我们会使用Apache HttpClient作为Http客户端,用于发送 HTTP 请求,并对响应进行处理.比如可以使用http客户端与第三方服务(如SSO服 ...

  5. 【转】GitHub 排名前 100 的安卓、iOS项目简介

    GitHub Android Libraries Top 100 简介 排名完全是根据 GitHub 搜索 Java 语言选择 (Best Match) 得到的结果, 然后过滤了跟 Android 不 ...

  6. GitHub Android Libraries Top 100 简介

    本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍, 至于排名完全是根据 GitHub 搜索 Java 语言选择 (Best Match) 得到的结果, 然后过 ...

  7. 2016年GitHub 排名前 100 的安卓、iOS项目简介(收藏)

    排名完全是根据 GitHub 搜索 Java 语言选择 (Best Match) 得到的结果, 然后过滤了跟 Android 不相关的项目, 所以排名并不具备任何官方效力, 仅供参考学习, 方便初学者 ...

  8. OkHttp:Java 平台上的新一代 HTTP 客户端

    OkHttp 简介 OkHttp 库的设计和实现的首要目标是高效.这也是选择 OkHttp 的重要理由之一.OkHttp 提供了对最新的 HTTP 协议版本 HTTP/2 和 SPDY 的支持,这使得 ...

  9. 64.GitHub 排名前100的android项目简介

    GitHub Android Libraries Top 100 简介 排名完全是根据 GitHub 搜索 Java 语言选择 (Best Match) 得到的结果, 然后过滤了跟 Android 不 ...

随机推荐

  1. BZOJ 3667 Pollard-rho &Miller-Rabin

    论O(1)快速乘和O(logn)快速乘的差距-. //By SiriusRen #include <cstdio> #include <algorithm> using nam ...

  2. struts2学习之基础笔记7

    第十二章 Struts 2的标记库 1 OGNL简介 Object-Grephic Navigtor Language 图对象导航语言 作用:图对象导航语言是Struts 2标记库中为其相应标记属性进 ...

  3. SpringBoot(十) 异步任务,定时任务和邮件任务

    异步任务 “异步调用”对应的是“同步调用”,同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行:异步调用指程序在顺序执行时,不等待异步调用的语句返回结果就执行后面的 ...

  4. const,var,let 区别

    js中const,var,let区别 1.const定义的变量不可以修改,而且必须初始化. 声明的是常量 1 const b = 2;//正确 2 // const b;//错误,必须初始化 3 co ...

  5. java和android文件加密小结

    最近遇到一个文件加密的问题,自己读写的,安全性虽然还可以,但是速度慢,影响体验. Cipher虽然速度相当快,但是android和java有某些api存在不兼容: 问题解决: 方法引用自:https: ...

  6. 使用CocoaPods更新第三方库出错的解决办法

    使用CocoaPods更新第三方库出错的解决办法 执行完pod install或pod update之后,控制台抛出以下警告信息: [!] The xx [Debug] target override ...

  7. Android ListView getView()方法重复调用导致position错位

    问题现状:Android ListView getView()方法重复调用导致position错位 解决办法:把ListView布局文件的layout_height属性改为fill_parent或者m ...

  8. 页面加载通过javascript来修改控件属性

    function changeFormElementStatus(tagNames) {            var tagNameArr = tagNames.split("," ...

  9. javaScript注释 to 颜文字

    将javascript 注释(alert.console)转化为 颜文字语言. http://utf-8.jp/public/aaencode.html

  10. java开发移动端之spring的restful风格定义

    https://www.ibm.com/developerworks/cn/web/wa-spring3webserv/index.html