其实一直想写这篇文章的,为什么不写呢?因为不想写,不要咬我.我要开始装逼了.接触okhttp是在2015年6月份左右,这已经过去了几年了,但是我对于它的爱犹如滔滔江水,连绵不绝,现在介绍一下,几年前我自己封装的okhttp工具类,拢共就几个类.不会对于造成学习的困扰.开始喽…
因为我已经把它封装为一个工具类,并上传到jcenter仓库,所以大家使用的话,直接gradle应用即可
compile 'cn.yuan.yu:library:1.0.2'
使用方法
第一步:初始化我们的工具类
public class MyApplication extends Application {
private static Handler mainHandler;
private static Context instance;
@Override
public void onCreate() {
super.onCreate();
instance = this;
mainHandler = new Handler();
/**
* 初始化okhttputils
* 第一个参数是是否提交json数据的形式还是表单的形式
* 第二份参数是请求返回的标识code
* 第三个参数是请求返回的正确的code值
* 第四个参数是请求返回的提示信息key
* 第五个参数是为了同步线程的问题
* 第六个参数是为了弹出提示信息的上下文
*/
OkHttpUtilsConfig.getInstance().init(false, "resultcode", "100", "msg", mainHandler,this);
}
}
第二步,直接调用使用喽,就是这么简单粗暴
JSONObject jsonObject = new JSONObject();
jsonObject.put("username", username);
jsonObject.put("password", pwd);
L.d("登录", jsonObject.toJSONString());
RequestPacket requestPacket = new RequestPacket();
requestPacket.url = ConstantUrl.getBaseUrl();
requestPacket.addArgument("data", jsonObject.toJSONString());
requestPacket.addArgument("query", "login");
OkHttpUtil.Request(RequestPacket.POST,requestPacket,new ResponseListener<RegistGetVCodeBean>() {
@Override
public void onSuccess(RegistGetVCodeBean registGetVCodeBean) {
//todo somethiing
}
@Override
public void onFailure(String responseresult) {
//todo somethiing
}
});
源码分析
第一步:看下我们封装的参数实体类
package cn.yuan.yu.library.bean;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* Created by yukuo on 2015/6/18.
* 这是一个请求实体类
*/
public class RequestPacket implements Serializable {
public static final int POST = 1000, GET = 1001;// 定义两个请求类型
public String url;// 请求的网络地址
public Map<String, Object> arguments = new HashMap<>();// 请求参数
public Map<String, String> headers = new HashMap<>();// 请求头
/**
* 这是一个添加请求参数的方法
*
* @param key
* @param value
*/
public void addArgument(String key, Object value) {
arguments.put(key, value);
}
/**
* 这是一个添加头信息参数的方法
*
* @param key
* @param value
*/
public void addHeader(String key, String value) {
headers.put(key, value);
}
/**
* 这是一个根据键获取参数值得方法
*
* @param key
* @return
*/
public Object getArgument(String key) {
return arguments.get(key);
}
/**
* 这是一个根据键获取头信息值得方法
*
* @param key
* @return
*/
public String getHeader(String key) {
return headers.get(key);
}
}
第二步看下我们封装的配置工具类
package cn.yuan.yu.library;
import android.content.Context;
import android.os.Handler;
/**
* Created by yukuoyuan on 2017/3/14.
* 这是一个okhttp的配置类
*/
public class OkHttpUtilsConfig {
//返回编码key
private String ResultCodeKey = "";
//返回编码正确值
private String ResultCodeValue = "";
//返回错误信息值
private String ResultMsgKey = "";
//是否提交json数据//否的话使用表单提交的形式
private boolean isPostJson = false;
//用于同步线程
private Handler mainHandler;
//是否展示和日志
private boolean isShowLog;
//上下文
private Context context;
/**
* 设置是否使用提交json的形式
* 不设置的话则使用提交表单的形式提交
*
* @param postJson 是否
*/
public void setPostJson(boolean postJson) {
isPostJson = postJson;
}
/**
* 设置返回的编码的key
*
* @param resultCodeKey key
*/
public void setResultCodeKey(String resultCodeKey) {
ResultCodeKey = resultCodeKey;
}
/**
* 设置返回正确的正确的value
*
* @param resultCodeValue
*/
public void setResultCodeValue(String resultCodeValue) {
ResultCodeValue = resultCodeValue;
}
/**
* 设置返回信息的字段key
*
* @param resultMsgKey key
*/
public void setResultMsgKey(String resultMsgKey) {
ResultMsgKey = resultMsgKey;
}
/**
* 这是一个初始化okhttputils的方法
*/
public void init(boolean postJson, String resultCodeKey, String resultCodeValue, String resultMsgKey, Handler mainHandler, Context context) {
setPostJson(postJson);
setResultCodeKey(resultCodeKey);
setResultCodeValue(resultCodeValue);
setResultMsgKey(resultMsgKey);
setMainHandler(mainHandler);
setContext(context);
}
public boolean isPostJson() {
return isPostJson;
}
public String getResultCodeKey() {
return ResultCodeKey;
}
public String getResultCodeValue() {
return ResultCodeValue;
}
public String getResultMsgKey() {
return ResultMsgKey;
}
public Handler getMainHandler() {
return mainHandler;
}
public void setMainHandler(Handler mainhandler) {
this.mainHandler = mainhandler;
}
public boolean isShowLog() {
return isShowLog;
}
public void setShowLog(boolean showLog) {
isShowLog = showLog;
}
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
private static OkHttpUtilsConfig sInstance;
private OkHttpUtilsConfig() {
}
public static OkHttpUtilsConfig getInstance() {
if (sInstance == null) {
synchronized (OkHttpUtilsConfig.class) {
if (sInstance == null) {
sInstance = new OkHttpUtilsConfig();
}
}
}
return sInstance;
}
}
第三步看下我们封装的回调接口
Ps:做了解析json的操作
package cn.yuan.yu.library.listener;
/**
* Created by yukuo on 2016/3/18.
* 这是一个服务器响应的监听器
*/
public abstract class ResponseListener<T> {
/**
* 这是一个返回正确信息的回调方法
*
* @param t
*/
public abstract void onSuccess(T t);
/**
* 这是一个返回错误信息的回调方法
*
* @param responseresult
*/
public abstract void onFailure(String responseresult);
}
第四步:看下我们重量级别的okhttputils
package cn.yuan.yu.library.utils;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import cn.yuan.yu.library.OkHttpUtilsConfig;
import cn.yuan.yu.library.ProgressResponseBody;
import cn.yuan.yu.library.R;
import cn.yuan.yu.library.bean.RequestPacket;
import cn.yuan.yu.library.listener.DonwloadResponseListener;
import cn.yuan.yu.library.listener.ResponseListener;
/**
* Created by yukuo on 2016/3/18.
* 这是一个okhttp请求的工具类
*/
public class OkHttpUtil {
private static final OkHttpClient mOkHttpClient = new OkHttpClient();
//请求类型
public static final MediaType mJSON = MediaType.parse("application/json; charset=utf-8");
//请求编码格式
private static final String CHARSET_NAME = "UTF-8";
static {
mOkHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);
mOkHttpClient.setReadTimeout(10, TimeUnit.SECONDS);
mOkHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
}
/**
* 这是一个get请求拼接请求路径的方法
*
* @param requestPacket 请求参数
* @return
*/
public static String appendUrl(RequestPacket requestPacket) {
return requestPacket.url + "?" + appendArguments(requestPacket);
}
/**
* 这是一个拼接get请求请求参数的方法
*
* @param requestPacket 请求参数
* @return
*/
public static String appendArguments(RequestPacket requestPacket) {
String argument = "";
for (String key : requestPacket.arguments.keySet()) {
if (requestPacket.getArgument(key) != null) {
if (argument.equals("")) {
argument = key + "=" + requestPacket.getArgument(key);
} else {
argument = argument + "&" + key + "=" + requestPacket.getArgument(key);
}
}
}
return argument;
}
/**
* 这是一个请求的网络的方法
*
* @param method 请求方式
* @param requestPacket 参数实体
* @param listener 回调
*/
public static void Request(int method, RequestPacket requestPacket, final ResponseListener listener) {
Request request = null;
Request.Builder builder = new Request.Builder();
//设置请求类型
builder.header("Content-Type", "application/json");
// 添加头信息
for (String key : requestPacket.headers.keySet()) {
if (requestPacket.getHeader(key) != null) {
builder.header(key, requestPacket.headers.get(key));
}
}
//设置请求的url
if (method == RequestPacket.POST) {
//如果是post请求
if (OkHttpUtilsConfig.getInstance().isPostJson()) {
RequestBody body = RequestBody.create(mJSON, new Gson().toJson(requestPacket.arguments));
request = new Request.Builder()
.url(requestPacket.url)
.post(body)
.build();
} else {
FormEncodingBuilder builer = new FormEncodingBuilder();
Set<String> keysets = requestPacket.arguments.keySet();
for (String key : keysets) {
builer.add(key, requestPacket.arguments.get(key).toString());
}
request = new Request.Builder()
.url(requestPacket.url)
.post(builer.build())
.build();
}
} else if (method == RequestPacket.GET) {
String url = appendUrl(requestPacket);
//如果是get请求
request = builder.url(url).build();
}
L.i("请求路径和参数", request.toString() + new Gson().toJson(requestPacket.arguments));
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(final Request request, final IOException e) {
sendFaliure("", listener, e);
}
@Override
public void onResponse(final Response response) throws IOException {
final String result = response.body().string();
JsonObject re = new Gson().toJsonTree(result).getAsJsonObject();
if (re.get(OkHttpUtilsConfig.getInstance().getResultCodeKey()).equals(OkHttpUtilsConfig.getInstance().getResultCodeValue())) {
SendSuccess(result, listener);
} else {
String responseresult = re.get(OkHttpUtilsConfig.getInstance().getResultMsgKey()).getAsString();
sendFaliure(responseresult, listener, null);
}
}
});
}
/**
* 发送成功回到
*
* @param result 返回的结果
* @param listener 回调监听
*/
private static void SendSuccess(final String result, final ResponseListener listener) {
OkHttpUtilsConfig.getInstance().getMainHandler().post(new Runnable() {
@Override
public void run() {
/**
* 获取要转换的json类型
*/
Type genType = listener.getClass().getGenericSuperclass();
Class clzss = (Class) ((ParameterizedType) genType).getActualTypeArguments()[0];
try {
L.i("返回的结果", result);
listener.onSuccess(new Gson().fromJson(result, clzss));
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* 发送失败的消息
*
* @param responseresult 返回的错误信息
* @param listener 回调监听
* @param e 异常
*/
private static void sendFaliure(final String responseresult, final ResponseListener listener, final IOException e) {
OkHttpUtilsConfig.getInstance().getMainHandler().post(new Runnable() {
@Override
public void run() {
listener.onFailure(responseresult);
if (e instanceof SocketTimeoutException) {
T.showLong(OkHttpUtilsConfig.getInstance().getContext(), R.string.net_error);
return;
} else if (e instanceof ConnectException) {
T.showLong(OkHttpUtilsConfig.getInstance().getContext(), R.string.net_null);
return;
}
}
});
}
/**
* 这是一个下载文件的方法
*
* @param donwloadurl 下载路径
* @param filepath 文件路径
* @param filename 文件名字
* @param donwloadResponseListener 回调监听
*/
public static void donwloadFile(String donwloadurl, final String filepath, final String filename, final DonwloadResponseListener donwloadResponseListener) {
//添加拦截器,自定义ResponseBody,添加下载进度
mOkHttpClient.networkInterceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) {
Response originalResponse = null;
try {
originalResponse = chain.proceed(chain.request());
} catch (IOException e) {
e.printStackTrace();
}
return originalResponse.newBuilder().body(
new ProgressResponseBody(originalResponse.body(), donwloadResponseListener))
.build();
}
});
//封装请求
Request request = new Request.Builder()
//下载地址
.url(donwloadurl)
.build();
//发送异步请求
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
/**
* 失败回调监听
*/
OkHttpUtilsConfig.getInstance().getMainHandler().post(new Runnable() {
@Override
public void run() {
donwloadResponseListener.onfailure();
}
});
}
@Override
public void onResponse(Response response) throws IOException {
//将返回结果转化为流,并写入文件
int len;
byte[] buf = new byte[2048];
InputStream inputStream = response.body().byteStream();
//可以在这里自定义路径
File file1 = new File(filepath + filename);
FileOutputStream fileOutputStream = new FileOutputStream(file1);
while ((len = inputStream.read(buf)) != -1) {
fileOutputStream.write(buf, 0, len);
}
fileOutputStream.flush();
fileOutputStream.close();
inputStream.close();
}
});
}
}
第五步:我们封装的下载文件相关类
下载回调
package cn.yuan.yu.library.listener;
/**
* Created by yukoyuan on 16/7/10.
* 这是一个下载文件的回调监听
*/
public interface DonwloadResponseListener {
/**
* @param bytesRead 已下载字节数
* @param contentLength 总字节数
* @param done 是否下载完成
* @deprecated 计算方式是 (100 * bytesRead) / contentLength
* 日志为 45%...
*/
void OnSuccess(long bytesRead, long contentLength, boolean done);
/**
* 下载失败的回调方法
*/
void onfailure();
}
其他代码和工具类
package cn.yuan.yu.library;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.ResponseBody;
import java.io.IOException;
import cn.yuan.yu.library.listener.DonwloadResponseListener;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;
/**
* Created by yukoyuan on 16/7/10.
* 这是一个下载文件实体的封装
*/
public class ProgressResponseBody extends ResponseBody {
private final ResponseBody responseBody;
private final DonwloadResponseListener progressListener;
private BufferedSource bufferedSource;
public ProgressResponseBody(ResponseBody responseBody, DonwloadResponseListener progressListener) {
this.responseBody = responseBody;
this.progressListener = progressListener;
}
@Override
public MediaType contentType() {
return responseBody.contentType();
}
@Override
public long contentLength() throws IOException {
return responseBody.contentLength();
}
@Override
public BufferedSource source() throws IOException {
if (bufferedSource == null) {
bufferedSource = Okio.buffer(source(responseBody.source()));
}
return bufferedSource;
}
private Source source(Source source) {
return new ForwardingSource(source) {
long totalBytesRead = 0L;
@Override
public long read(Buffer sink, long byteCount) throws IOException {
long bytesRead = super.read(sink, byteCount);
totalBytesRead += bytesRead != -1 ? bytesRead : 0;
progressListener.OnSuccess(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
return bytesRead;
}
};
}
}
日志类和Toast类
package cn.yuan.yu.library.utils;
import android.util.Log;
import cn.yuan.yu.library.OkHttpUtilsConfig;
/**
* Created by yukuo on 2015/11/18.
* 这是一个log的工具类
*/
public class L {
private static boolean flag = OkHttpUtilsConfig.getInstance().isShowLog();
public static void e(String tag, String text) {
if (flag) {
Log.e(tag, text);
}
}
public static void d(String tag, String text) {
if (flag) {
Log.d(tag, text);
}
}
public static void i(String tag, String text) {
if (flag) {
Log.i(tag, text);
}
}
public static void v(String tag, String text) {
if (flag) {
Log.v(tag, text);
}
}
public static void w(String tag, String text) {
if (flag) {
Log.w(tag, text);
}
}
public static void wtf(String tag, String text) {
if (flag) {
Log.wtf(tag, text);
}
}
}
package cn.yuan.yu.library.utils;
import android.content.Context;
import android.widget.Toast;
/**
* Created by yukuo on 2016/1/9.
* 这是一个toast的工具类
*/
public class T {
public static boolean isShow = true;
/**
* 短时间显示Toast类型为CharSequence的数据
*
* @param context
* @param message
*/
public static void showShort(Context context, CharSequence message) {
if (isShow)
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
/**
* 短时间显示Toast类型为int的数据
*
* @param context
* @param message
*/
public static void showShort(Context context, int message) {
if (isShow)
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
/**
* 长时间显示Toast类型为CharSequence的数据
*
* @param context
* @param message
*/
public static void showLong(Context context, CharSequence message) {
if (isShow)
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
/**
* 长时间显示Toast类型为int的数据
*
* @param context
* @param message
*/
public static void showLong(Context context, int message) {
if (isShow)
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
/**
* 自定义显示Toast时间类型为CharSequence的数据
*
* @param context
* @param message
* @param duration
*/
public static void show(Context context, CharSequence message, int duration) {
if (isShow)
Toast.makeText(context, message, duration).show();
}
/**
* 自定义显示Toast时间类型为int的数据
*
* @param context
* @param message
* @param duration
*/
public static void show(Context context, int message, int duration) {
if (isShow)
Toast.makeText(context, message, duration).show();
}
}
至此我们工具类封装完成了,看一下代码,并没有多少,有没有感觉很简单啊,没那么复杂,有什么问题,欢迎留言给我,也欢迎给我star,谢谢思密达们