Okhttp有一段时间了,个人感觉这套封装方法还不错,共享出来供网友们参考
项目git地址https://github.com/HuangPugang/okhttpframework.git
欢迎大家来找出不足,共同进步
使用方法
/**
* get 请求(已测可用)
* @param v
*/
public void get(View v){
OkClient.request(ParamManager.getNewsListParam(1, 8), null, new IResponseCallback() {
@Override
public void onSuccess(int tag, Object object) {
Log.e("HPG",object.toString());
}
@Override
public void onError(int tag, OkError error) {
}
});
}
/**
* post请求 (已测可用)
* @param v
*/
public void post(View v){
OkClient.request(ParamManager.getPost(1, 8), null, new IResponseCallback() {
@Override
public void onSuccess(int tag, Object object) {
Log.e("HPG",object.toString());
}
@Override
public void onError(int tag, OkError error) {
}
});
}
/**
* 上传文件(未测,在其他app中已测可用)
* @param v
*/
public void upload(View v){
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
OkClient.upload(ParamManager.upload(1, file), null, new IResponseCallback() {
@Override
public void onSuccess(int tag, Object object) {
Log.e("HPG",object.toString());
}
@Override
public void onError(int tag, OkError error) {
}
});
}
/**
* 下载文件(已测可用)
* @param v
*/
public void download(View v){
OkClient.download(ParamManager.download(), null, null, new ProgressListener() {
@Override
public void onProgress(long bytesWritten, long contentLength, long percent) {
Log.e("HPG",percent+"%");
}
});
}
OkClient.class,这个类主要是提供给对外的使用接口,get,Post,Upload,Download都是通过这个类来进行调用的
package com.paul.okhttpframework.okhttp.manager;
import com.paul.okhttpframework.okhttp.bean.OkTag;
import com.paul.okhttpframework.okhttp.bean.RequestParam;
import com.paul.okhttpframework.okhttp.callback.IResponseCallback;
import com.paul.okhttpframework.okhttp.progress.ProgressListener;
/**
* Created by Paul on 15/12/8.
*/
public class OkClient {
private static String TAG = OkClient.class.getSimpleName();
private OkClient() {
}
/**
* 普通post和get请求
*
* @param param 参数封装,不能为空
* @param cls 返回的数据封装的类型,如果为null,则返回String
* @param callback 回调接口,每一个回调接口与tag绑定
*/
public static void request(RequestParam param, Class<?> cls, IResponseCallback callback) {
OkTag OkTag = new OkTag(param.getTag());
NetManager.getInstance().request(OkTag, param, cls, callback, null);
}
/**
* 普通post和get请求
*
* @param param 参数封装,不能为空
* @param cls 返回的数据封装的类型,如果为null,则返回String
* @param callback 回调接口,每一个回调接口与tag绑定
*/
public static void upload(RequestParam param, Class<?> cls, IResponseCallback callback) {
OkTag OkTag = new OkTag(param.getTag());
NetManager.getInstance().request(OkTag, param, cls, callback, null);
}
/**
* 文件上传
*
* @param param 参数封装,不能为空
* @param cls 返回的数据封装的类型,如果为null,则返回String
* @param callback 回调接口,每一个回调接口与tag绑定
* @param listener 上传进度监听 可为空
*/
public static void upload(RequestParam param, Class<?> cls, IResponseCallback callback, ProgressListener listener) {
OkTag OkTag = new OkTag(param.getTag());
NetManager.getInstance().request(OkTag, param, cls, callback, listener);
}
/**
* 文件下载
*
* @param param 参数封装,不能为空
* @param cls 返回的数据封装的类型,如果为null,则返回String
* @param callback 回调接口,每一个回调接口与tag绑定
*/
public static void download(RequestParam param, Class<?> cls, IResponseCallback callback) {
OkTag OkTag = new OkTag(param.getTag());
NetManager.getInstance().request(OkTag, param, cls, callback, null);
}
/**
* 文件下载
*
* @param param 参数封装,不能为空
* @param cls 返回的数据封装的类型,如果为null,则返回String
* @param callback 回调接口,每一个回调接口与tag绑定
* @param listener 下载进度监听
*/
public static void download(RequestParam param, Class<?> cls, IResponseCallback callback, ProgressListener listener) {
OkTag OkTag = new OkTag(param.getTag());
NetManager.getInstance().request(OkTag, param, cls, callback, listener);
}
/**
* 取消请求
*
* @param tag
*/
public void cancelRequest(int... tag) {
NetManager.getInstance().cancelRequest(tag);
}
public void cancelAllRequest() {
NetManager.getInstance().cancelAllRequest();
}
}
NetManager.class 实现类,这个类主要对okhttp的具体操作进行了封装
package com.paul.okhttpframework.okhttp.manager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import com.google.gson.Gson;
import com.paul.okhttpframework.okhttp.bean.OkError;
import com.paul.okhttpframework.okhttp.bean.OkResult;
import com.paul.okhttpframework.okhttp.bean.OkTag;
import com.paul.okhttpframework.okhttp.bean.RequestParam;
import com.paul.okhttpframework.okhttp.callback.IResponseCallback;
import com.paul.okhttpframework.okhttp.progress.ProgressListener;
import com.paul.okhttpframework.okhttp.progress.ProgressRequestBody;
import com.paul.okhttpframework.util.AppConfig;
import com.paul.okhttpframework.util.DLog;
import com.paul.okhttpframework.util.NetUtil;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
* 网络管理页面
*/
public class NetManager {
public static final int GET = 100;
public static final int POST = 101;
public static final int PUT = 102;
public static final int DELETE = 103;
public static final int DOWNLOAD = 104;
public static final int UPLOAD = 105;
private static final String TAG = NetManager.class.getSimpleName();
private static final int DEFAULT_TIME_OUT = 15000;
private static final int CODE_SUCCESS = 0;
private static final int CODE_FAILED = 1;
private static final int CODE_TOKEN_ERROR = 2;
private static NetManager sInstance;
//handler the result of request
private OkHttpClient mOkHttpClient;
private InternalHandler mHandler;
private Gson mGson;
//request callbacks
private ConcurrentHashMap<OkTag, IResponseCallback> mCallbacks = new ConcurrentHashMap<>();
//request calls
private ConcurrentHashMap<OkTag, Call> mAsyncCalls = new ConcurrentHashMap<>();
private NetManager() {
if (mOkHttpClient == null) {
synchronized (NetManager.class) {
mOkHttpClient = new OkHttpClient.Builder()
.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS)
.writeTimeout(DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS)
.readTimeout(DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS)
.build();
}
}
}
public static NetManager getInstance() {
if (null == sInstance) {
synchronized (NetManager.class) {
sInstance = new NetManager();
}
}
return sInstance;
}
/**
* @param tag
* @param requestParam
* @param cls
* @param callback
*/
public void request(final OkTag tag, final RequestParam requestParam, final Class<?> cls, final IResponseCallback callback, final ProgressListener progressListener) {
addCallback(tag, callback);
if (requestParam == null) {
//almost tell the developer that he/she forget the RequestBean
sendFailedMessage(tag, getOkError("参数错误"));
return;
}
if (NetUtil.isNetAvailable()) {
try {
switch (requestParam.getMethod()) {
case GET:
doGet(tag, requestParam.getUrl(), requestParam.getHeaders(),
requestParam.getParams(), cls);
break;
case POST:
doPost(tag, requestParam.getUrl(), requestParam.getHeaders(),
requestParam.getParams(), cls);
break;
case DOWNLOAD:
doDownload(tag, requestParam.getUrl(), callback, progressListener);
break;
case UPLOAD:
doUpload(tag, requestParam.getUrl(), requestParam.getParams(),
requestParam.getFiles(), cls, callback, progressListener);
break;
}
} catch (Exception e) {
//unexpected error
e.printStackTrace();
sendFailedMessage(tag, new OkError("请求失败"));
}
} else {
sendFailedMessage(tag, new OkError("当前网络已断开,请检查网络后重试"));
}
}
/**
* get request
*
* @param tag
* @param url
* @param headers
* @param params
* @param cls
* @throws Exception
*/
private void doGet(final OkTag tag, String url, final Map<String, String> headers,
final Map<String, String> params, final Class<?> cls) throws Exception {
String requestUrl = null;
// 如果是GET请求,则请求参数在URL中
if (params != null && !params.isEmpty() && params.size() != 0) {
String param = urlEncode(params);
requestUrl = url + "?" + param;
} else {
requestUrl = url;
}
DLog.i(TAG, "tag=" + tag.getTag() + " GET:" + requestUrl);
Request.Builder requestBuilder = new Request.Builder();
if (null != headers && !headers.isEmpty() && headers.size() != 0) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
if (entry.getKey() != null && entry.getValue() != null) {
requestBuilder.header(entry.getKey(), entry.getValue());
}
}
}
Request request = requestBuilder
.url(requestUrl)
.build();
deliveryRequest(tag, request, cls);
}
/**
* post request
*
* @param tag
* @param url
* @param headers
* @param params
* @param cls
*/
private void doPost(final OkTag tag, String url, final Map<String, String> headers,
final Map<String, String> params, final Class<?> cls) {
FormBody.Builder builder = new FormBody.Builder();
if (params != null && !params.isEmpty() && params.size() != 0) {
for (Map.Entry<String, String> entry : params.entrySet()) {
if (entry.getKey() != null && entry.getValue() != null) {
builder.add(entry.getKey(), entry.getValue());
}
}
}
RequestBody formBody = builder.build();
//build request header
Request.Builder requestBuilder = new Request.Builder();
if (null != headers && !headers.isEmpty() && headers.size() != 0) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
if (entry.getKey() != null && entry.getValue() != null) {
requestBuilder.header(entry.getKey(), entry.getValue());
}
}
}
DLog.i(TAG, "tag=" + tag.getTag() + " POST:" + url);
DLog.i(TAG, "tag=" + tag.getTag() + " params= " + params.toString());
Request request = requestBuilder
.url(url)
.post(formBody)
.build();
deliveryRequest(tag, request, cls);
}
//fileupload
private void doUpload(final OkTag tag, String url, Map<String, String> params, Map<String, File> files, final Class<?> cls, IResponseCallback callback, ProgressListener progressListener) {
DLog.i(TAG, url);
DLog.i(TAG, "tag=" + tag.getTag() + " params= " + params.toString());
MultipartBody.Builder builder = new MultipartBody.Builder();
if (params != null && !params.isEmpty() && params.size() != 0) {
for (Map.Entry<String, String> entry : params.entrySet()) {
if (entry.getKey() != null && entry.getValue() != null) {
builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + entry.getKey() + "\""),
RequestBody.create(null, entry.getValue()));
}
}
}
if (files != null && !files.isEmpty() && files.size() != 0) {
for (Map.Entry<String, File> entry : files.entrySet()) {
if (entry.getKey() != null && entry.getValue() != null) {
RequestBody fileBody = null;
fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), entry.getValue());
builder.addPart(Headers.of("Content-Disposition",
"form-data; name=\"" + entry.getKey() + "\"; filename=\"" + entry.getValue().getName() + "\""),
fileBody);
}
}
}
RequestBody requestBody = builder.build();
Request request;
if (progressListener != null) {//带进度条
request = new Request.Builder()
.url(url)
.post(new ProgressRequestBody(requestBody, progressListener))
.build();
} else {
request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
}
deliveryRequest(tag, request, cls);
}
/**
* 下载
*
* @param tag
* @param callback
* @param progressListener
*/
private void doDownload(final OkTag tag, final String url, final IResponseCallback callback, final ProgressListener progressListener) {
Request request = new Request.Builder()
.url(url)
.build();
// OkHttpClient client = new OkHttpClient.Builder()
// .connectTimeout(DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS)
// .writeTimeout(DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS)
// .readTimeout(DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS)
// .addInterceptor(new Interceptor() {
// @Override
// public Response intercept(Chain chain) throws IOException {
// //拦截
// Response originalResponse = chain.proceed(chain.request());
// //包装响应体并返回
// return originalResponse.newBuilder()
// .body(new ProgressResponseBody(originalResponse.body(), progressListener))
// .build();
// }
// })
// .build();
Call call = mOkHttpClient.newCall(request);
addCall(tag, call);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
OkError OkError = getOkError("服务器连接异常,请稍后再试");
sendFailedMessage(tag, OkError);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
File file = new File(AppConfig.getLocalProductDownloadPath(), getFileName(url));
//此处可以增加判断文件是否存在的逻辑
InputStream is = null;
byte[] buf = new byte[2048];
int len = 0;
FileOutputStream fos = null;
try {
is = response.body().byteStream();
long contentLen = response.body().contentLength();
long downloadLen = 0;
fos = new FileOutputStream(file);
long currentPercent = 0;
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
downloadLen += len;
if (progressListener != null) {
if (downloadLen * 100 / contentLen - currentPercent >= 1) {
currentPercent = downloadLen * 100 / contentLen;
progressListener.onProgress(downloadLen, contentLen, currentPercent);
}
}
}
fos.flush();
sendSuccessMessage(tag, file);
} catch (Exception e) {
e.printStackTrace();
sendFailedMessage(tag, getOkError("下载失败"));
} finally {
try {
if (is != null) is.close();
} catch (IOException e) {
}
try {
if (fos != null) fos.close();
} catch (IOException e) {
}
}
}
});
}
/**
* 处理post get upload返回结果 download单独处理
*
* @param tag
* @param request
* @param cls
*/
private void deliveryRequest(final OkTag tag, final Request request, final Class<?> cls) {
Call call = mOkHttpClient.newCall(request);
addCall(tag, call);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
OkError OkError = getOkError("服务器连接异常,请稍后再试");
sendFailedMessage(tag, OkError);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
try {
String strResult = response.body().string();
DLog.i(TAG, "tag=" + tag.getTag() + " result=" + strResult);
Object result;
if (cls != null) {
Gson gson = new Gson();
result = gson.fromJson(strResult, cls);
} else { //没有指定类型,直接返回string
result = strResult;
}
if (result == null) {
sendFailedMessage(tag, getOkError("数据为空"));
} else {
sendSuccessMessage(tag, result);
}
} catch (Exception e) {
e.printStackTrace();
sendFailedMessage(tag, getOkError("解析错误"));
}
}
});
}
/**
* 获得文件名
*
* @param path
* @return
*/
private String getFileName(String path) {
int separatorIndex = path.lastIndexOf("/");
return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1, path.length());
}
/**
* package params
*
* @param params
* @return
* @throws UnsupportedEncodingException
*/
private String urlEncode(Map<String, String> params)
throws UnsupportedEncodingException {
StringBuffer sb2 = new StringBuffer();
for (Map.Entry<String, String> entry : params.entrySet()) {
if (entry.getKey() != null && entry.getValue() != null) {
sb2.append(entry.getKey());
sb2.append("=");
sb2.append(URLEncoder.encode(entry.getValue(), "utf-8").toString());
sb2.append("&");
}
}
String s = "";
if (sb2.length() != 0) {
s = sb2.substring(0, sb2.length() - 1);
}
return s;
}
/**
* the IResponseCallback matches the specified tag
*
* @param iResponseCallback
* @param tag
* @return void
* @throw
*/
private void addCallback(OkTag tag, IResponseCallback iResponseCallback) {
if (iResponseCallback == null) {
mCallbacks.put(tag, new IResponseCallback() {
@Override
public void onSuccess(int tag, Object object) {
}
@Override
public void onError(int tag, OkError object) {
}
});
return;
}
mCallbacks.put(tag, iResponseCallback);
}
private void addCall(OkTag tag, Call call) {
mAsyncCalls.put(tag, call);
}
private Call getAndRemoveCall(OkTag tag) {
if (mAsyncCalls != null && mAsyncCalls.size() != 0 && mAsyncCalls.containsKey(tag)) {
Call call = mAsyncCalls.get(tag);
mAsyncCalls.remove(tag);
return call;
}
return null;
}
/**
* get and remove IResponseCallback threw the specified tag
*
* @param tag
* @return IResponseCallback
* @throw
*/
private IResponseCallback getAndRemoveCallback(OkTag tag) {
if (mCallbacks != null && mCallbacks.size() != 0 && mCallbacks.containsKey(tag)) {
IResponseCallback iResponseCallback = mCallbacks.get(tag);
DLog.i(TAG, "Before_removeTag_HashMap.size===" + mCallbacks.size());
mCallbacks.remove(tag);
return iResponseCallback;
}
return null;
}
/**
* @param tag
* @return void
* @throw
*/
private void removeCallback(OkTag tag) {
if (mCallbacks.containsKey(tag)) {
mCallbacks.remove(tag);
}
}
private void removeCall(OkTag tag) {
if (mAsyncCalls.containsKey(tag)) {
mAsyncCalls.remove(tag);
}
}
/**
* sendFailedMessage
*
* @param tag
* @param object
*/
private void sendSuccessMessage(OkTag tag, Object object) {
//remove call while you request success
getAndRemoveCall(tag);
IResponseCallback iResponseCallback = getAndRemoveCallback(tag);
if (iResponseCallback != null) {
Message message = getHandler().obtainMessage();
OkResult handlerBean = new OkResult(tag, object, iResponseCallback);
message.obj = handlerBean;
message.arg1 = CODE_SUCCESS;
message.sendToTarget();
}
}
/**
* sendSuccessMessage
*
* @param tag
* @param OkError
*/
private void sendFailedMessage(OkTag tag, OkError OkError) {
//remove call while you request failed
getAndRemoveCall(tag);
IResponseCallback iResponseCallback = getAndRemoveCallback(tag);
if (iResponseCallback != null) {
OkResult handlerBean = new OkResult(tag, OkError, iResponseCallback);
Message message = getHandler().obtainMessage();
message.obj = handlerBean;
message.arg1 = CODE_FAILED;
message.sendToTarget();
}
}
private Handler getHandler() {
synchronized (NetManager.class) {
if (mHandler == null) {
mHandler = new InternalHandler();
}
return mHandler;
}
}
// private Gson getGson() {
// if (mGson == null) {
// synchronized (NetManager.class) {
// GsonBuilder builder = new GsonBuilder();
// builder.registerTypeAdapter(JsonInteger.class, new JsonIntegerTypeAdapter());
// builder.registerTypeAdapter(JsonFloat.class, new JsonFloatTypeAdapter());
// builder.registerTypeAdapter(JsonLong.class, new JsonLongTypeAdapter());
// mGson = builder.create();
// }
// }
// return mGson;
// }
private OkError getOkError(String msg) {
OkError OkError = new OkError("请求失败");
return OkError;
}
/**
* check weather tag has removed
* <p>if true exist else removedx
*
* @param tag
* @return
*/
private boolean checkTag(OkTag tag) {
if (mCallbacks != null && mCallbacks.size() != 0) {
if (mCallbacks.containsKey(tag)) {
return true;
}
}
return false;
}
/**
* cancel request
* <p> if calls contain the request ,remove it
*
* @param tags
*/
public void cancelRequest(int... tags) {
if (tags != null && tags.length != 0) {
List<OkTag> cancelCalls = new ArrayList<>();
List<OkTag> cancelCallbacks = new ArrayList<>();
for (int i = 0; i < tags.length; i++) {
int tag = tags[i];
if (mAsyncCalls != null && mAsyncCalls.size() != 0) {
for (Map.Entry<OkTag, Call> entry : mAsyncCalls.entrySet()) {
if (entry.getKey().getTag() == tag) {
cancelCalls.add(entry.getKey());
}
}
}
if (mCallbacks != null && mCallbacks.size() != 0) {
for (Map.Entry<OkTag, IResponseCallback> entry : mCallbacks.entrySet()) {
if (entry.getKey().getTag() == tag) {
cancelCallbacks.add(entry.getKey());
}
}
}
}
for (int i = 0; i < cancelCalls.size(); i++) {
Call call = mAsyncCalls.get(cancelCalls.get(i));
call.cancel();
mAsyncCalls.remove(cancelCalls.get(i));
}
for (int i = 0; i < cancelCallbacks.size(); i++) {
mCallbacks.remove(cancelCallbacks.get(i));
}
}
}
public void cancelAllRequest() {
mAsyncCalls.clear();
mCallbacks.clear();
}
//handle the result of the request
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@Override
public void handleMessage(Message msg) {
OkResult handlerBean = (OkResult) msg.obj;
OkTag tag = handlerBean.getTag();
IResponseCallback iResponseCallback = handlerBean.getResponseCallback();
switch (msg.arg1) {
case CODE_SUCCESS:
Object object = handlerBean.getObject();
if (tag != null) {
iResponseCallback.onSuccess(tag.getTag(), object);
}
break;
case CODE_FAILED:
OkError OkError = (OkError) handlerBean.getObject();
if (tag != null) {
iResponseCallback.onError(tag.getTag(), OkError);
}
break;
}
}
}
}
RequestParam.class 参数封装类,请求需要用到的参数都封装到这个类里面,包括 string,file等各种类型
package com.paul.okhttpframework.okhttp.bean;
import com.paul.okhttpframework.okhttp.API;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class RequestParam {
private int tag ;
private int method;
private String url;
protected Map<String, String> params;
protected Map<String, File> files;
protected Map<String, String> headers;
public RequestParam(int tag, String url){
this(API.GET, tag, url);
}
public RequestParam(int method, int tag, String url) {
this(method, tag, url, true);
}
/**
* @param method
* @param url
* @param withBaseURL 是否使用baseURL
*/
public RequestParam(int method, int tag, String url, boolean withBaseURL) {
init(method,tag,url,withBaseURL);
}
private void init(int method, int tag,String url,boolean withBaseURL){
this.method = method;
this.tag = tag;
if (withBaseURL) {
this.url = API.SERVER_URL + url;
}else{
this.url = url;
}
this.params = new HashMap<>();
this.files = new HashMap<>();
this.headers = new HashMap<>();
}
public int getMethod() {
return method;
}
public void setMethod(int method) {
this.method = method;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public void put(String key, Object value) {
if (key != null && value != null) {
if (value instanceof File){
putFile(key,(File)value);
}else {
params.put(key, value+"");
}
}
}
public void putFile(String key, File file) {
if (key != null && file != null) {
files.put(key, file);
}
}
public void putHeader(String key, String value) {
if (key != null && value != null) {
headers.put(key, value);
}
}
public int getTag() {
return tag;
}
public void setTag(int tag) {
this.tag = tag;
}
public void setParams(Map<String, String> params) {
this.params = params;
}
public void setFiles(Map<String, File> files) {
this.files = files;
}
public void setHeaders(Map<String, String> headers) {
this.headers = headers;
}
public Map<String, String> getParams() {
return params;
}
public Map<String, File> getFiles() {
return files;
}
public Map<String, String> getHeaders() {
return headers;
}
}
是不是很简单,赶紧下载使用吧。