最近半年来身边开发的朋友越来越多的提到OkHttp,上谷歌百度一下,确实OkHttp成了时下最火的HTTP框架,于是我也开始放下Volley,转而关注OkHttp,五一期间仔细看了官方WiKi介绍(我喜欢学习官方的文档),现在把自己整理的官方教程分享给大家,希望给初学者带来帮助。
OkHttp官网地址:http://square.github.io/okhttp/
OkHttp GitHub地址:https://github.com/square/okhttp
官网的自我介绍:
HTTP is the way modern applications network. It’s how we exchange data & media. Doing HTTP efficiently makes your stuff load faster and saves bandwidth.
OkHttp is an HTTP client that’s efficient by default:
• HTTP/2 support allows all requests to the same host to share a socket.
• Connection pooling reduces request latency (if HTTP/2 isn’t available).
• Transparent GZIP shrinks download sizes.
• Response caching avoids the network completely for repeat requests.
OkHttp perseveres when the network is troublesome: it will silently recover from common connection problems. If your service has multiple IP addresses OkHttp will attempt alternate addresses if the first connect fails. This is necessary for IPv4+IPv6 and for services hosted in redundant data centers. OkHttp initiates new connections with modern TLS features (SNI, ALPN), and falls back to TLS 1.0 if the handshake fails.
Using OkHttp is easy. Its request/response API is designed with fluent builders and immutability. It supports both synchronous blocking calls and async calls with callbacks.
OkHttp supports Android 2.3 and above. For Java, the minimum requirement is 1.7.
概括起来说OkHttp是一款优秀的HTTP框架,它支持get请求和post请求,支持基于Http的文件上传和下载,支持加载图片,支持下载文件透明的GZIP压缩,支持响应缓存避免重复的网络请求,支持使用连接池来降低响应延迟问题。
(一)导入Jar包
点击下面链接下载最新v3.2.0 JAR
http://repo1.maven.org/maven2/com/squareup/okhttp3/okhttp/3.2.0/okhttp-3.2.0.jar
(二)通过构建方式导入
MAVEN
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.2.0</version>
</dependency>
GRADLE
compile 'com.squareup.okhttp3:okhttp:3.2.0'
基本要求
Requests(请求)
每一个HTTP请求中都应该包含一个URL,一个GET或POST方法以及Header或其他参数,当然还可以含特定内容类型的数据流。
Responses(响应)
响应则包含一个回复代码(200代表成功,404代表未找到),Header和定制可选的body。
基本使用在日常开发中最常用到的网络请求就是GET和POST两种请求方式。
HTTP GET
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
}
Request是OkHttp中访问的请求,Builder是辅助类,Response即OkHttp中的响应。
Response类:
public boolean isSuccessful()
Returns true if the code is in [200..300), which means the request was successfully received, understood, and accepted.
response.body()返回ResponseBody类
可以方便的获取string
public final String string() throws IOException
Returns the response as a string decoded with the charset of the Content-Type header. If that header is either absent or lacks a charset, this will attempt to decode the response body as UTF-8.
Throws:
IOException
当然也能获取到流的形式:
public final InputStream byteStream()
HTTP POST
POST提交Json数据
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
f (response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
}
使用Request的post方法来提交请求体RequestBody
POST提交键值对
OkHttp也可以通过POST方式把键值对数据传送到服务器
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody formBody = new FormEncodingBuilder()
.add("platform", "android")
.add("name", "bug")
.add("subject", "XXXXXXXXXXXXXXX")
.build();
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
}
案例
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal">
<Button
android:id="@+id/bt_get"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="乌云Get请求"/>
<Button
android:id="@+id/bt_post"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="乌云Post请求"/>
</LinearLayout>
<TextView
android:id="@+id/tv_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Java代码:
由于android本身是不允许在UI线程做网络请求操作的,所以我们自己写个线程完成网络操作
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button bt_get;
private Button bt_post;
final OkHttpClient client = new OkHttpClient();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
bt_get=(Button)findViewById(R.id.bt_get);
bt_post=(Button)findViewById(R.id.bt_post);
bt_get.setOnClickListener(this);
bt_post.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.bt_get:
getRequest();
break;
case R.id.bt_post:
postRequest();
break;
}
}
private void getRequest() {
final Request request=new Request.Builder()
.get()
.tag(this)
.url("http://www.wooyun.org")
.build();
new Thread(new Runnable() {
@Override
public void run() {
Response response = null;
try {
response = client.newCall(request).execute();
if (response.isSuccessful()) {
Log.i("WY","打印GET响应的数据:" + response.body().string());
} else {
throw new IOException("Unexpected code " + response);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
private void postRequest() {
RequestBody formBody = new FormEncodingBuilder()
.add("","")
.build();
final Request request = new Request.Builder()
.url("http://www.wooyun.org")
.post(formBody)
.build();
new Thread(new Runnable() {
@Override
public void run() {
Response response = null;
try {
response = client.newCall(request).execute();
if (response.isSuccessful()) {
Log.i("WY","打印POST响应的数据:" + response.body().string());
} else {
throw new IOException("Unexpected code " + response);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
执行结果:
Synchronous Get(同步Get)
下载一个文件,打印他的响应头,以string形式打印响应体。
响应体的 string() 方法对于小文档来说十分方便、高效。但是如果响应体太大(超过1MB),应避免适应 string()方法 ,因为他会将把整个文档加载到内存中。对于超过1MB的响应body,应使用流的方式来处理body。
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());
}