1.写在前面:

  网络请求框架层出不穷,像google的volley,xutils等等。听说Okhttp性能很高,最近写新项目,决定用Okhttp来尝试一下(原谅我是小白,第一次使用,以前还是用volley),以此来记录一下自己的心得。

2.首先来介绍一下Okhttp:

  Okhttp出自鼎鼎大名的Square,官方github地址:​​https://github.com/square/okhttp​​;它基本包含所有常用的网络请求,同步、异步的get、post请求,文件上传下载等等,废话不说,直接进入教程

3.Okhttp的使用:

1)首先添加依赖:

Download the latest JAR or grab via Maven:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.6.0</version>
</dependency>
or Gradle:
compile 'com.squareup.okhttp3:okhttp:3.6.0'

还在用eclipse的童鞋也可以下载jar使用,不过抓紧时间换Android Studio吧;

2)同时别忘了添加添加网络权限:

<uses-permission android:name="android.permission.INTERNET"/>

3)开始编写代码:

http同步get请求:

/**
* 同步的Get请求
*
* @param url
* @return responseStr
* @throws IOException
*/
public static String getSync(String url) throws IOException {
// 创建OKHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
// 创建一个Request
final Request request = new Request.Builder()
.url(url)
.build();
Call call = okHttpClient.newCall(request);
// 返回值为response
Response response = call.execute();
// 将response转化成String
String responseStr = response.body().string();
return responseStr;
}

  OKHttp请求成功的返回值为Response ,一般可以通过response.body().string()获取返回的字符串;也可以通过response.body().bytes()获取返回的二进制字节数组;也可以通过response.body().byteStream()获取返回的inputStream。 
  

http异步get请求:

/**
* 异步的Get请求
*
* @param url url
*/
public static void getAsyn(String url) {
// 创建OKHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
// 创建一个Request
final Request request = new Request.Builder()
.url(url)
.build();
Call call = okHttpClient.newCall(request);
// 请求加入调度
call.enqueue(new Callback() {
// 请求失败的回调
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}

// 请求成功的回调
@Override
public void onResponse(Call call, Response response) throws IOException {
// 将response转化成String
String responseStr = response.body().string();
}
});
}

  同上OKHttp请求成功的返回值为Response ,一般可以通过response.body().string()获取返回的字符串;值得注意的是它的返回值是在子线程中而不是UI线程,想要在UI线程中使用,还需要使用handler等,例如:

// 请求成功的回调
@Override
public void onResponse(Call call, Response response) throws IOException {
// 将response转化成String
String responseStr = response.body().string();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), responseStr,
Toast.LENGTH_SHORT).show();
}
}
}

  这样http的异步get请求就完成了,如果每次请求都写如此多的代码而且返回值还不是在UI线程,那每发送一次请求都很麻烦,看到这,你一定会想到封装,没错,将OKHttp封装成一个工具类,每次使用直接去调用就简单多了,在本文最后我也会提供我自己对OKHttp的简单封装,供大家参考。

http同步post请求:

/**
* 同步的Post请求
*
* @param url url
* @param params params
* @return responseStr
* @throws IOException
*/
public static String postSync(String url, Map<String, String> params)
throws IOException {
// RequestBody
RequestBody requestBody;
if (params == null) {
params = new HashMap<>();
}
// 创建OKHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
FormBody.Builder builder = new FormBody.Builder();
/**
* 在这对添加的参数进行遍历
*/
for (Map.Entry<String, String> map : params.entrySet()) {
String key = map.getKey();
String value;
/**
* 判断值是否是空的
*/
if (map.getValue() == null) {
value = "";
} else {
value = map.getValue();
}
/**
* 把key和value添加到formBody中
*/
builder.add(key, value);
}
requestBody = builder.build();
// 创建一个Request
final Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
Call call = okHttpClient.newCall(request);
// 返回值为response
Response response = call.execute();
// 将response转化成String
String responseStr = response.body().string();
return responseStr;
}

   大家知道,发送post请求时,参数是包含在请求体中的,所以我们去构造RequestBody,最后完成我们Request的构造。

http异步post请求:

/**
* 异步的Post请求
*
* @param url url
* @param params params
* @return responseStr
*/
public static void postAsyn(String url, Map<String, String> params) {
// RequestBody
RequestBody requestBody;
if (params == null) {
params = new HashMap<>();
}
// 创建OKHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
FormBody.Builder builder = new FormBody.Builder();
/**
* 在这对添加的参数进行遍历
*/
for (Map.Entry<String, String> map : params.entrySet()) {
String key = map.getKey();
String value;
/**
* 判断值是否是空的
*/
if (map.getValue() == null) {
value = "";
} else {
value = map.getValue();
}
/**
* 把key和value添加到formBody中
*/
builder.add(key, value);
}
requestBody = builder.build();
// 创建一个Request
final Request request = new Request.Builder()
.url(url)
.post(requestBody)
.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 {
// 将response转化成String
String responseStr = response.body().string();
}
});
}

  以上是基于http的异步post请求,上面的例子添加的请求参数是Map,当然也可以添加其他类型的参数,如:

// post传参(byte)
RequestBody byteBody = RequestBody.create(MediaType.parse("application/octet-stream; charset=utf-8"), mapToBytes(params));

mapToBytes(params)方法是将params转化成byte

http的文件上传:

/**
* 基于http的文件上传
* 通过addFormDataPart可以添加多个上传的文件
*/
public void uploadMultiFile() {
// 创建OKHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
File file = new File(Environment.getExternalStorageDirectory(), "pic.png");
RequestBody fileBody = RequestBody.create
(MediaType.parse("application/octet-stream"), file);
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("image", "pic.png", fileBody)
.build();
Request request = new Request.Builder()
.url("填写url地址")
.post(requestBody)
.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 {

}
});
}

http的文件下载:

/**
* 基于http的下载文件请求
*
* @param downloadUrl 下载地址
*/
public static void downloadRequest(String downloadUrl) {
// 创建OKHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(downloadUrl)
.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 {
// 下载成功后执行的操作
}
});
}

OKHttp的简单封装使用(NetRequest工具类):

  以上是OKHttp常用的请求,其他请求类似,不再重复。下面对OKHttp进行简单的封装,使其使用方便,不必每次都写大量的重复方法,同时直接将返回值Response传递到UI线程,将其封装在OKHttp的工具类中,简化代码,下面直接贴代码:

package com.guifa.okhttpdemo.http;

import android.os.Handler;
import android.os.Looper;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
* Created by GuiFa on 2017/2/3.
* 网络请求工具类
*/
public class NetRequest {
private static NetRequest netRequest;
private static OkHttpClient okHttpClient; // OKHttp网络请求
private Handler mHandler;

private NetRequest() {
// 初始化okhttp 创建一个OKHttpClient对象,一个app里最好实例化一个此对象
okHttpClient = new OkHttpClient();
okHttpClient.newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS);
mHandler = new Handler(Looper.getMainLooper());
}

/**
* 单例模式 获取NetRequest实例
*
* @return netRequest
*/
private static NetRequest getInstance() {
if (netRequest == null) {
netRequest = new NetRequest();
}
return netRequest;
}

//-------------对外提供的方法Start--------------------------------

/**
* 建立网络框架,获取网络数据,异步get请求(Form)
*
* @param url url
* @param params key value
* @param callBack data
*/
public static void getFormRequest(String url, Map<String, String> params, DataCallBack callBack) {
getInstance().inner_getFormAsync(url, params, callBack);
}

/**
* 建立网络框架,获取网络数据,异步post请求(Form)
*
* @param url url
* @param params key value
* @param callBack data
*/
public static void postFormRequest(String url, Map<String, String> params, DataCallBack callBack) {
getInstance().inner_postFormAsync(url, params, callBack);
}

  /**
* 建立网络框架,获取网络数据,异步post请求(json)
*
* @param url url
* @param params key value
* @param callBack data
*/
public static void postJsonRequest(String url, Map<String, String> params, DataCallBack callBack) {
getInstance().inner_postJsonAsync(url, params, callBack);
}
//-------------对外提供的方法End--------------------------------

/**
* 异步get请求(Form),内部实现方法
*
* @param url url
* @param params key value
*/
private void inner_getFormAsync(String url, Map<String, String> params, final DataCallBack callBack) {
if (params == null) {
params = new HashMap<>();
}
// 请求url(baseUrl+参数)
final String doUrl = urlJoint(url, params);
// 新建一个请求
final Request request = new Request.Builder().url(doUrl).build();
//执行请求获得响应结果
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
deliverDataFailure(request, e, callBack);
}

@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) { // 请求成功
//执行请求成功的操作
String result = response.body().string();
deliverDataSuccess(result, callBack);
} else {
throw new IOException(response + "");
}
}
});
}

/**
* 异步post请求(Form),内部实现方法
*
* @param url url
* @param params params
* @param callBack callBack
*/
private void inner_postFormAsync(String url, Map<String, String> params, final DataCallBack callBack) {
RequestBody requestBody;
if (params == null) {
params = new HashMap<>();
}
FormBody.Builder builder = new FormBody.Builder();
/**
* 在这对添加的参数进行遍历
*/
for (Map.Entry<String, String> map : params.entrySet()) {
String key = map.getKey();
String value;
/**
* 判断值是否是空的
*/
if (map.getValue() == null) {
value = "";
} else {
value = map.getValue();
}
/**
* 把key和value添加到formbody中
*/
builder.add(key, value);
}
requestBody = builder.build();
//结果返回
final Request request = new Request.Builder().url(url).post(requestBody).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
deliverDataFailure(request, e, callBack);
}

@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) { // 请求成功
//执行请求成功的操作
String result = response.body().string();
deliverDataSuccess(result, callBack);
} else {
throw new IOException(response + "");
}
}
});
}

  /**
* post请求传json
*
* @param url url
* @param callBack 成功或失败回调
* @param params params
*/
private void inner_postJsonAsync(String url, Map<String, String> params,final DataCallBack callBack) {
// 将map转换成json,需要引入Gson包
String mapToJson = new Gson().toJson(params);
final Request request = buildJsonPostRequest(url, mapToJson);
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
deliverDataFailure(request, e, callBack);
}

@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) { // 请求成功
//执行请求成功的操作
String result = response.body().string();
deliverDataSuccess(result, callBack);
} else {
throw new IOException(response + "");
}
}
});
}

  /**
* Json_POST请求参数
*
* @param url url
* @param json json
* @return requestBody
*/
private Request buildJsonPostRequest(String url, String json) {
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
return new Request.Builder().url(url).post(requestBody).build();
}

/**
* 分发失败的时候调用
*
* @param request request
* @param e e
* @param callBack callBack
*/
private void deliverDataFailure(final Request request, final IOException e, final DataCallBack callBack) {
/**
* 在这里使用异步处理
*/
mHandler.post(new Runnable() {
@Override
public void run() {
if (callBack != null) {
callBack.requestFailure(request, e);
}
}
});
}

/**
* 分发成功的时候调用
*
* @param result result
* @param callBack callBack
*/
private void deliverDataSuccess(final String result, final DataCallBack callBack) {
/**
* 在这里使用异步线程处理
*/
mHandler.post(new Runnable() {
@Override
public void run() {
if (callBack != null) {
try {
callBack.requestSuccess(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}

/**
* 数据回调接口
*/
public interface DataCallBack {

void requestSuccess(String result) throws Exception;

void requestFailure(Request request, IOException e);
}

/**
* 拼接url和请求参数
*
* @param url url
* @param params key value
* @return String url
*/
private static String urlJoint(String url, Map<String, String> params) {
StringBuilder endUrl = new StringBuilder(url);
boolean isFirst = true;
Set<Map.Entry<String, String>> entrySet = params.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
if (isFirst && !url.contains("?")) {
isFirst = false;
endUrl.append("?");
} else {
endUrl.append("&");
}
endUrl.append(entry.getKey());
endUrl.append("=");
endUrl.append(entry.getValue());
}
return endUrl.toString();
}
}

NetRequest工具类的简单使用:

String url = "网络请求的地址";
HashMap<String, String> params = new HashMap<>();
// 添加请求参数
params.put("key", "value");
// ...
NetRequest.getFormRequest(url, params, new NetRequest.DataCallBack() {
@Override
public void requestSuccess(String result) throws Exception {
// 请求成功的回调
}

@Override
public void requestFailure(Request request, IOException e) {
// 请求失败的回调
}
});

  至于同步get、post请求同理,而且个人感觉使用较少,便没有写出,文件下载和上传同理。以上便是我对OKHttp的使用和认识,当然OKHttp远远不止这些,以后再慢慢补充。以上均为个人观点,如有错误,欢迎留言指出,以便及时修正。