网上有很多OkHttp使用的教程,而我今天要给大家分享的是我自己对OkHttp的使用并且做了简单的封装,希望能给你们带来帮助,话不多说了下面直接上干货了(我使用的是Android Studio)。
官方的文档
OkHttp官网地址:http://square.github.io/okhttp/
OkHttp GitHub地址:https://github.com/square/okhttp
OKHttp的使用
Android Studio用户在 Gradle中添加:
compile'com.squareup.okhttp3:okhttp:3.8.1'
compile 'com.squareup.okio:okio:1.13.0'
Eclipse的用户,添加依赖包即可,Jar包下载地址: okhttp3_Jar okio_Jar
干货来了(直接上代码)
1.请求地址配置
/**
* 网络访问地址定义
* @author zcq
* Created by 2016/4/25.
*/
public class ApiConfig {
public final static String API_BSAE = "http://192.168.1.118/help/";
}
2.接口错误定义
/**
* 接口错误定义
* @author zcq
* Created by 2017/4/25.
*/
public enum ErrorCode {
/**
* 无错误
*/
None,
/**
* 网络错误
*/
NetworkError,
/**
* 服务器错误
*/
ServerError,
/**
* 数据错误
*/
DataError
}
3.数据接口监听器
/**
* 数据侦听器接口定义,用于向接口传递单条数据
* @author zcq
* Created by 2016/4/25.
*/
public interface OnDataListener<T> extends OnErrorListener{
/**
* 向接口传递单条数据
* @param isSuccess 接口调用是否成功
* @param data 待传递的单条数据
* @param errorCode 接口调用失败时错误码
* @param errorReason 接口调用失败时的原因
*/
void onData(boolean isSuccess, T data, int errorCode, String errorReason);
}
/**
* 数据侦听器接口定义,用于向接口传递单条数据
* @author zcq
* Created by 2016/4/25.
*/
public interface OnListListener<T> extends OnErrorListener{
/**
* 向接口传递多条数据
* @param isSuccess 接口调用是否成功
* @param data 待传递的多条数据
* @param errorCode 接口调用失败时错误码
* @param errorReason 接口调用失败时的原因
*/
void onList(boolean isSuccess, List<T> data, int errorCode, String errorReason);
}
/**
* @author zcq
* Created by 2016/4/25.
*/
public interface OnImageListener {
void onImage(int position, String url, Bitmap bitmap);
}
/**
* 错误侦听器接口定义,用于向接口传递错误信息
* @author zcq
* Created by 2016/4/25.
*/
public interface OnErrorListener {
/**
* 向接口传递错误信息
* @param code 待传递的错误信息
*/
void onError(ErrorCode code);
}
4.与服务器通讯接口类定义
/**
* 与服务器通讯接口类定义
* @author zcq
* Created by 2016/4/25.
*/
public class HttpHelper {
private final static boolean DEBUG = true;
private final static String TAG = "help/HttpHelper";
protected final static int MESSAGE_DATA = 0;
protected final static int MESSAGE_ERROR = 1;
/**
* 接收到网络数据
* @param event 事件的标识
* @param response 所接收到的数据
*/
protected void onData(int event, String response){
}
/**
* 接收到网络错误
* @param event 事件的标识
* @param code 所接收到的错误码
*/
protected void onError(int event, ErrorCode code){
}
static class UIHandler extends Handler {
private final WeakReference<HttpHelper> ref;
UIHandler(HttpHelper act) {
this.ref = new WeakReference<>(act);
}
@Override
public void handleMessage(Message msg) {
HttpHelper act = ref.get();
if (msg.what == MESSAGE_DATA) {
act.onData(msg.arg1, msg.obj != null ? msg.obj.toString() : null);
} else if (msg.what == MESSAGE_ERROR) {
act.onError(msg.arg1, (ErrorCode) msg.obj);
} else {
super.handleMessage(msg);
}
}
}
private final UIHandler mHandler = new UIHandler(this);
/**
* 开始异步访问网络接口
* @param event 事件编号
* @param url 接口地址
* @param params 待提交的参数
*/
protected synchronized void beginRequest(final int event, final String url, final Map<String, String> params){
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient client = new OkHttpClient();
FormBody.Builder formBodayBuilder = new FormBody.Builder();
//参数处理
if (params != null) {
for (String param : params.keySet()) {
String value = params.get(param);
if (value != null) {
formBodayBuilder.add(param, value);
}
}
}
//设置发出的 request
Request post = new Request.Builder()
.url(url) //请求的地址
.post(formBodayBuilder.build()) //请求的参数
.tag(event) //请求标识
.build();
try {
//获取 response
Response response = client.newCall(post).execute();
if (response.isSuccessful()) {
String res = response.body().string();
// Log.i("----API请求返回值----","----***************---res:"+res);
if (res != null) {
mHandler.obtainMessage(MESSAGE_DATA, event, 0, res).sendToTarget();
} else {
mHandler.obtainMessage(MESSAGE_ERROR, event, 0, ErrorCode.ServerError).sendToTarget();
}
} else {
if (DEBUG) {
String res = response.body().toString();
if (res != null) {
Log.d(TAG, res);
}
}
mHandler.obtainMessage(MESSAGE_ERROR, event, 0, ErrorCode.ServerError).sendToTarget();
}
} catch (IOException e) {
mHandler.obtainMessage(MESSAGE_ERROR, event, 0, ErrorCode.NetworkError).sendToTarget();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 开始异步上传文件
* @param event 事件编号
* @param url 接口地址
* @param params 待提交的参数
*filesam files 待上传的文件
*/
protected synchronized void beginUpload(final int event, final String url,
final Map<String, String> params,
final Map<String, String> files) {
new Thread(new Runnable() {
@Override
public synchronized void run() {
OkHttpClient client = new OkHttpClient();
//以表单方式上传图片文件
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
//非文件参数处理
if (params != null) {
for (String param : params.keySet()) {
String value = params.get(param);
if (value != null) {
builder.addFormDataPart(param, value);
}
}
}
//文件参数处理 TODO: MediaType 可提出作为参数
MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
int i = 0;
if(files != null){
for (String key : files.keySet()){
File file = new File(files.get(key));
if(file != null){
builder.addFormDataPart("file"+i, file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file));
}
i++;
}
}
MultipartBody requestBody = builder.build();
//请求
Request post = new Request.Builder()
.url(url) //请求的地址
.post(requestBody) //请求的参数
.tag(event) //请求标识
.build();
try {
//获取 response
Response response = client.newCall(post).execute();
if (response.isSuccessful()) {
String res = response.body().string();
if (res != null) {
mHandler.obtainMessage(MESSAGE_DATA, event, 0, res).sendToTarget();
} else {
mHandler.obtainMessage(MESSAGE_ERROR, event, 0, ErrorCode.ServerError).sendToTarget();
}
} else {
if (DEBUG) {
String res = response.body().toString();
if (res != null) {
Log.d(TAG, res);
}
}
mHandler.obtainMessage(MESSAGE_ERROR, event, 0, ErrorCode.ServerError).sendToTarget();
}
} catch (IOException e) {
mHandler.obtainMessage(MESSAGE_ERROR, event, 0, ErrorCode.NetworkError).sendToTarget();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 开始异步访问网络接口
* @param event 事件编号
* @param url 接口地址
*/
protected synchronized void beginRequest(int event, String url) {
beginRequest(event, url, null);
}
}
5.返回的 JSON 数据进行解析的帮助类
/**
* 对 HTTP 返回的 JSON 数据进行解析的帮助类
* @author zcq
* Created by 2016/4/25.
*/
public class JsonHttpHelper extends HttpHelper{
private final static boolean DEBUG = true;
private final static String TAG = "help/HttpHelper";
/**
* 接收到网络数据
*
* @param event 事件的标识
* @param response 所接收到的数据
*/
@Override
protected void onData(int event, String response) {
try {
// 开始解析数据
JSONObject jsonObject = new JSONObject(response);
JsonResult jsonResult = new JsonResult();
jsonResult.isSuccess = jsonObject.optBoolean("IsSuccess");
if (jsonResult.isSuccess) {
jsonResult.returnValue = jsonObject.optString("ReturnValue");
} else {
jsonResult.errorCode = jsonObject.optInt("ErrorCode");
jsonResult.errorReason = jsonObject.optString("ErrorMessage");
}
onResult(event, jsonResult);
} catch (JSONException e) {
onError(event, ErrorCode.DataError);
}
}
/**
* 接口调用完成时解析后的数据
*
* @param event 事件的标识
* @param result 解析后的数据
*/
protected void onResult(int event, JsonResult result) {
}
/**
* 将解析后的数据交给指定侦听器进行处理
*
* @param result 待处理的数据
* @param cls 返回值对应的类
* @param <T> 返回值对应的数据类型
* @param listener 指定的侦听器
*/
@SuppressWarnings("unchecked")
protected <T> void handleData(@NonNull JsonResult result, @NonNull Class<T> cls, @Nullable OnErrorListener listener) {
// 检查侦听器有无注册
if (listener == null) {
if (DEBUG) {
Log.d(TAG, "the listener not used.");
}
return;
}
// 接口返回失败时不解析返回值
if (!result.isSuccess) {
if (listener instanceof OnDataListener) {
((OnDataListener<T>) listener).onData(false, null, result.errorCode, result.errorReason);
} else if (listener instanceof OnListListener) {
((OnListListener<T>) listener).onList(false, null, result.errorCode, result.errorReason);
}
return;
}
// 将返回值字符串解析成对象
ObjectMapper objectMapper = new ObjectMapper();
try {
if (listener instanceof OnDataListener) {
// 返回的数据为单个对象
T returnValue;
if (cls.getSimpleName().equals("String")) {
returnValue = (T) result.returnValue;
} else {
returnValue = objectMapper.readValue(result.returnValue, cls);
}
((OnDataListener<T>) listener).onData(true, returnValue, 0, null);
} else if (listener instanceof OnListListener) {
// 返回的数据为列表数据
List<T> returnValue = objectMapper.readValue(
result.returnValue, TypeFactory.defaultInstance()
.constructCollectionType(List.class, cls));
((OnListListener<T>) listener).onList(true, returnValue, 0, null);
}
} catch (IOException e) {
listener.onError(ErrorCode.DataError);
}
}
}
6.请求返回值JSON格式定义
/**
* 网络请求返回值 JSON 格式定义
* @author zcq
* Created by 2016/4/25.
*/
public class JsonResult {
/**
* 判断接口是否调用成功
*/
public boolean isSuccess;
/**
* 接口返回值
*/
public String returnValue;
/**
* 接口返回错误时的Code
*/
public int errorCode;
/**
* 接口返回的错误信息
*/
public String errorReason;
}
以上就是我使用OkHttp自定义的封装请求相关的所有代码了,下面则是使用的测试样例
- TestApi定义
/**
* @author zcq
* Created by 2016/4/26.
*/
public class TestApi extends JsonHttpHelper{
//事件定义
private final static int EVENT_HOST_API_BASE = 1000;
private final static int EVENT_GET_PERSONAGE_LIST = EVENT_HOST_API_BASE + 1;
//访问地址的定义
private final static String HOST_SITE = ApiConfig.API_BSAE;
//接口路径
private final static String URL_GET_PERSONAGE_LIST = HOST_SITE + "mobile/star/getDataLs"; //获取数据列表接口
/**
* 接口调用完成时解析后的数据
* @param event 事件的标识
* @param result 解析后的数据
*/
@Override
protected void onResult(int event, JsonResult result) {
switch (event) {
case EVENT_GET_PERSONAGE_LIST:
handleData(result, Personage.class, mOnGetPersonageLsListener);
break;
}
}
/**
* 接收到网络错误
* @param event 事件的标识
* @param code 所接收到的错误码
*/
@Override
protected void onError(int event, ErrorCode code) {
switch (event) {
case EVENT_GET_PERSONAGE_LIST:
if(mOnGetPersonageLsListener != null){
mOnGetPersonageLsListener.onError(code);
}
break;
}
}
/*********************** 获取List<Entity> **********************/
//获取数据列表接口
private OnListListener<Personage> mOnGetPersonageLsListener;
/**
* 获取数据列表接口
* @param listener 待设置的侦听器
*/
public void setOnGetPersonageLsListener(OnListListener<Personage> listener){
this.mOnGetPersonageLsListener = listener;
}
/**
* 获取数据列表接口
* @param pageNum 当前页
* @param pageSize 分页数
*/
public void getPersonageLs(int pageNum, int pageSize){
Map<String, String> params = new HashMap<String, String>();
params.put("pageNum", String.valueOf(pageNum));
params.put("pageSize", String.valueOf(pageSize));
params.put("channel_num","android");
beginRequest(EVENT_GET_PERSONAGE_LIST, URL_GET_PERSONAGE_LIST, params);
}
/*********************** 获取Entity String Boolean**********************/
//使用 OnDataListener<Entity> OnDataListener<String> OnDataListener<Boolean>
//配置 handleData(result, Entity.class, mOnListener);
//配置 handleData(result, Boolean.class, mOnListener);
//配置 handleData(result, String.class, mOnListener);
}
- 测试Activity
public class TestAct extends Activity{
private TestApi mApi;
private TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_ui_test_api);
mApi = new TestApi();
text = (TextView)findViewById(R.id.text);
//Button按钮
findViewById(R.id.list_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mApi.getPersonageLs(0, 2);
}
});
//设置侦听器
mApi.setOnGetPersonageLsListener(new OnListListener<Personage>() {
@Override
public void onList(boolean isSuccess, List<Personage> data, int errorCode, String errorReason) {
if(isSuccess){
text.setText(data.get(0).desc);
Toast.makeText(TestAct.this, "List_成功!", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(TestAct.this, "List_失败!", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onError(ErrorCode code) {
if(code.equals(ErrorCode.DataError)){
Toast.makeText(TestAct.this, "数据错误!", Toast.LENGTH_SHORT).show();
}else if(code.equals(ErrorCode.NetworkError)){
Toast.makeText(TestAct.this, "网络错误!", Toast.LENGTH_SHORT).show();
}else if(code.equals(ErrorCode.ServerError)){
Toast.makeText(TestAct.this, "服务器错误!", Toast.LENGTH_SHORT).show();
}
}
});
}
}
- 数据实体类 bean
/**
* 实体类
* @author zcq
* Created by 2016/4/26.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Personage implements Serializable {
@JsonProperty("column_id")
public String id;
@JsonProperty("column_name")
public String name;
@JsonProperty("column_context")
public String context;
@JsonProperty("column_desc")
public String desc;
@JsonProperty("column_icon")
public String imgUrl;
@JsonProperty("create_time")
public String create_time;
}
最后附上API接口模板_样例说明
- 返回值样例(标准Json格式)
//返回值为Boolean样例:
{
"IsSuccess":true,
"ReturnValue":true,
"ErrorMessage":"",
"ErrorCode":0
}
//返回值为String样例:
{
"IsSuccess":true,
"ReturnValue": "http://139.196.192.92/images/info/20160303/20160303110822_head_846141.jpg",
"ErrorMessage":"",
"ErrorCode":0
}
//返回值为List<Entity>样例:
{
"IsSuccess":true,
"ReturnValue":"[{
"commentId":239,
"infoId":6375,
"authorId":40,
"author":"青牙",
"head_img_url":"http://139.196.192.92/images/info/20160303/20160303110822_head_846141.jpg",
"comment_content":"感觉可怜可怜",
"time":"2017-04-26"
},
{
"commentId":238,
"infoId":6375,
"authorId":40,
"author":"青牙",
"head_img_url":"http://139.196.192.92/images/info/20160303/20160303110822_head_846141.jpg",
"comment_content":"过来看看",
"time":"2017-04-26"}]"
"ErrorMessage":"",
"ErrorCode":0
}
//返回值为Entity样例:
{
"IsSuccess":true,
"ReturnValue":"{
"infoId":6375,
"title":"评《锦绣未央》抄袭:放任大\"IP\"抄袭只会劣币驱逐良币",
"comment_count":4,
"time":"2017-04-26",
"is_like":"0",
"token":"827885c0-db46-4234-a22b-af7aae0f31d9",
"shareUrl":"http://139.196.192.92/cbtt/admin/info/viewDetailOnPhone?infoId=6375",
}",
"ErrorMessage":"",
"ErrorCode":0
}