前文:现在的网络框架中最火的是retrofit与okhttp,retrofit看了一部分,封装了,但是看大部分都是与rxjava一起使用,而很多大神也对okhttp做了一层包装,封装出一些网络框架,像okgo,okhttpUtils,但是别人封装的再华丽,不代表适合自己,所以本wolf分享一篇原生封装的okhttp。
首先,需要导入gradle :
implementation 'com.squareup.okhttp3:okhttp:3.4.1'
okhttp则分为Request请求与response响应。
request请求体:每一个HTTP请求中都应该包含一个URL,一个GET或POST方法以及Header或其他参数,当然还可以含特定内容类型的数据流。
response 响应码:响应则包含一个回复代码(200代表成功,404代表未找到),Header和定制可选的body。
okhttp配置:
包括设置响应时间,读取时间等,先配置了,便可使用。
private final OkHttpClient client;
client = new OkHttpClient.Builder()
.connectTimeout(60000, TimeUnit.MILLISECONDS)
.writeTimeout(60000, TimeUnit.MILLISECONDS)
.readTimeout(60000, TimeUnit.MILLISECONDS)
.build();
基本请求:GET 请求 ,POST请求
GET请求
Request.Builder builder = new Request.Builder();
Request request = builder.get().url(url).build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException error) {
//响应失败
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//响应成功
}
});
POST请求:
JSON格式传输数据:
RequestBody body = RequestBody.create(JSON, jsonObject.toString());
client.newCall(
new Request.Builder()
.url(url)
// .headers()//添加头
.post(body)
.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
LogUtil.i("http response " + response);
if (response.isSuccessful()) {
}
}else {
}
}
});
可以看出来,json传输,需要把jsonObject转成json串,放到RequestBody中,再请求okhttp中自带的CallBack即可。
表单传输:
OkHttpClient client = new OkHttpClient();
MultipartBody multipartBody =new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("groupId",""+groupId)//添加键值对参数
.addFormDataPart("title","title")
.addFormDataPart("file",file.getName(),RequestBody.create(MediaType.parse("file/*"), file))//添加文件
.build();
final Request request = new Request.Builder()
.url(URLContant.CHAT_ROOM_SUBJECT_IMAGE)
.post(multipartBody)
.build();
client.newCall(request).enqueue(new Callback() {//此处省略回调});
按照okhttp原生写法为此。还有传byte数组,流数据的,应用较少。
okhttp设置头文件:
Request request = new Request.Builder()
.url("http://www.baidu.com")
.header("User-Agent", "OkHttp Headers.java")
.addHeader("token", "myToken")
.build();
okhttp原生写法很简单,但是使用中,需要自己做一层封装,并且在使用中容易遇到很多问题,像多次点击,点击一次请求了,回调没回来,又点击了进行请求,可能会导致出错。原生写法,没有进行封装,使用起来很不方便,分享一下,我对okhttp做的封装。
CancelAble 类,方便取消请求
public class CancelAble {
Call call;
public void cancel(){
if(call != null){
call.cancel();
call = null;
}
}
}
Subscriber回调类
public interface Subscriber<T> {
void onCompleted(T result);
void onError(Throwable e);
Class<?> getType();
}
自己封装的okhttpCallBack类,方便回调
public class OkHttpCallback implements okhttp3.Callback {
private static final String TAG = "OkHttpCallback";
private Subscriber subscriber;
private Class<? extends BaseBean> type;
private Handler mHandler = new Handler(Looper.getMainLooper());
private Gson gson;
String body;
public OkHttpCallback(@NonNull Subscriber subscriber) {
this.subscriber = subscriber;
type = subscriber.getType();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response == null) {
return;
}
body = response.body().string();
if (subscriber != null) {
if (type == null){
subscriber.onError(new Exception("type can't be null"));
return;
}
if ("String".equals(type.getSimpleName())) {
mHandler.post(new Runnable() {
@Override
public void run() {
subscriber.onCompleted(body);
}
});
} else {
gson = new Gson();
try {
final BaseBean bean = gson.fromJson(body, type);
if (bean != null) {
mHandler.post(new Runnable() {
@Override
public void run() {
subscriber.onCompleted(bean);
}
});
}
} catch (final Exception e) {
mHandler.post(new Runnable() {
@Override
public void run() {
subscriber.onError(e);
}
});
}
}
}
}
@Override
public void onFailure(Call call, final IOException e) {
if (subscriber != null) {
mHandler.post(new Runnable() {
@Override
public void run() {
subscriber.onError(e);
}
});
}
}
}
get请求方法封装:
public CancelAble get(String url, final OkHttpCallback callback) {
cleanCancelAbleList();
Request.Builder builder = new Request.Builder();
Request request = builder.get().url(url).build();
CancelAble cancelAble = new CancelAble();
cancelAble.call = client.newCall(request);
cancelAble.call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException error) {
if (callback == null) return;
if (call.isCanceled()) return;
callback.onFailure(call, error);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
callback.onResponse(call, response);
}
});
return cancelAble;
}
post请求方法封装(json):
public CancelAble post(String url, JSONObject jsonObject, OkHttpCallback callback) {
cleanCancelAbleList();
Request request = getStringPostRequest(url, jsonObject);
Log.d(TAG, "接口post:" + url + (jsonObject == null ? "" : jsonObject.toString()));
CancelAble cancelAble = new CancelAble();
cancelAble.call = client.newCall(request);
callList.add(new WeakReference<>(cancelAble));
execCallback(cancelAble.call, callback);
return cancelAble;
}
private void execCallback(Call call, final OkHttpCallback callback) {
call.enqueue(new Callback() {
public void onResponse(final Call call, final Response response) throws IOException {
callback.onResponse(call, response);
}
public void onFailure(Call call, IOException e) {
Log.e(TAG, "onFailure", e);
if (callback == null) return;
if (call.isCanceled()) return;
callback.onFailure(call, e);
}
});
}
表单请求,带file
public void postPic(String url, Map<String, String> map, Map<String, File> paths, final OkHttpCallback callback) {
cleanCancelAbleList();
Request.Builder builder = new Request.Builder();
builder.url(url);
//TODO 传递过来的集合必须做逻辑判断,不能为空,否则下面报空指针
MultipartBody.Builder multiBuilder = new MultipartBody.Builder()
.setType(MultipartBody.FORM);
//遍历map中所有参数到builder
if (map != null && map.size() != 0) {
if (map.keySet() != null && map.keySet().size() != 0) {
for (String key : map.keySet()) {
if (key != null) {//可以是空串
String value = map.get(key);
if (value != null) {
multiBuilder.addFormDataPart(key, value);
}
}
}
}
}
//遍历paths中所有图片绝对路径到builder,并约定key如“upload”作为后台接受多张图片的key
if (paths != null && paths.size() != 0) {
if (paths.keySet() != null && paths.keySet().size() != 0) {
for (String name : paths.keySet()) {
if (name != null && !"".equals(name)) {//空串无意义
File imgPath = paths.get(name);
//TODO 文件路径不能为空
if (imgPath != null && !"".equals(imgPath)) {
multiBuilder.addFormDataPart(name, "file.png", RequestBody.create(MEDIA_TYPE_PNG, imgPath));
}
}
}
}
}
builder.post(multiBuilder.build());
Request request = builder.build();
Call postCall = client.newCall(request);
postCall.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException error) {
Log.i("xjz", error.toString());
if (callback == null) return;
if (call.isCanceled()) return;
callback.onFailure(call, error);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// getJsonData(response, requestCode, paramsMaps, mHandler);
Log.i("xjz", response.toString());
callback.onResponse(call, response);
}
});
}
完整的Okutils类:
public class OKUtils {
private final OkHttpClient client;
private final ArrayList<WeakReference<CancelAble>> callList = new ArrayList<>(0);
private static final String TAG = "okhttp";
public static final OKUtils okClient = new OKUtils();
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
public OKUtils() {
client = new OkHttpClient.Builder()
.connectTimeout(60000, TimeUnit.MILLISECONDS)
.writeTimeout(60000, TimeUnit.MILLISECONDS)
.readTimeout(60000, TimeUnit.MILLISECONDS)
.build();
}
public static OKUtils getInstance() {
return okClient;
}
public CancelAble post(String url, JSONObject jsonObject, OkHttpCallback callback) {
cleanCancelAbleList();
Request request = getStringPostRequest(url, jsonObject);
Log.d(TAG, "接口post:" + url + (jsonObject == null ? "" : jsonObject.toString()));
CancelAble cancelAble = new CancelAble();
cancelAble.call = client.newCall(request);
callList.add(new WeakReference<>(cancelAble));
execCallback(cancelAble.call, callback);
return cancelAble;
}
public CancelAble get(String url, final OkHttpCallback callback) {
cleanCancelAbleList();
Request.Builder builder = new Request.Builder();
Request request = builder.get().url(url).build();
CancelAble cancelAble = new CancelAble();
cancelAble.call = client.newCall(request);
cancelAble.call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException error) {
if (callback == null) return;
if (call.isCanceled()) return;
callback.onFailure(call, error);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
callback.onResponse(call, response);
}
});
return cancelAble;
}
/**
* 直接传file
* @param url
* @param map
* @param paths
* @param callback
*/
public void postPic(String url, Map<String, String> map, Map<String, File> paths, final OkHttpCallback callback) {
cleanCancelAbleList();
Request.Builder builder = new Request.Builder();
builder.url(url);
//TODO 传递过来的集合必须做逻辑判断,不能为空,否则下面报空指针
MultipartBody.Builder multiBuilder = new MultipartBody.Builder()
.setType(MultipartBody.FORM);
//遍历map中所有参数到builder
if (map != null && map.size() != 0) {
if (map.keySet() != null && map.keySet().size() != 0) {
for (String key : map.keySet()) {
if (key != null) {//可以是空串
String value = map.get(key);
if (value != null) {
multiBuilder.addFormDataPart(key, value);
}
}
}
}
}
//遍历paths中所有图片绝对路径到builder,并约定key如“upload”作为后台接受多张图片的key
if (paths != null && paths.size() != 0) {
if (paths.keySet() != null && paths.keySet().size() != 0) {
for (String name : paths.keySet()) {
if (name != null && !"".equals(name)) {//空串无意义
File imgPath = paths.get(name);
//TODO 文件路径不能为空
if (imgPath != null && !"".equals(imgPath)) {
multiBuilder.addFormDataPart(name, "file.png", RequestBody.create(MEDIA_TYPE_PNG, imgPath));
}
}
}
}
}
builder.post(multiBuilder.build());
Request request = builder.build();
Call postCall = client.newCall(request);
postCall.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException error) {
Log.i("xjz", error.toString());
if (callback == null) return;
if (call.isCanceled()) return;
callback.onFailure(call, error);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// getJsonData(response, requestCode, paramsMaps, mHandler);
Log.i("xjz", response.toString());
callback.onResponse(call, response);
}
});
}
public void cancelAll() {
for (WeakReference<CancelAble> item : callList)
if (item.get() != null)
item.get().cancel();
callList.clear();
}
private void cleanCancelAbleList() {
if (callList.size() <= client.dispatcher().getMaxRequests())
return;
ArrayList<WeakReference> readyRemoveList = new ArrayList<>(callList.size());
for (WeakReference<CancelAble> item : callList)
if (item.get() == null)
readyRemoveList.add(item);
callList.removeAll(readyRemoveList);
}
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private Request getStringPostRequest(String url, JSONObject jsonObject) {
RequestBody body = RequestBody.create(JSON, jsonObject.toString());
return new Request.Builder()
.url(url)
.post(body)
.build();
}
private void execCallback(Call call, final OkHttpCallback callback) {
call.enqueue(new Callback() {
public void onResponse(final Call call, final Response response) throws IOException {
callback.onResponse(call, response);
}
public void onFailure(Call call, IOException e) {
Log.e(TAG, "onFailure", e);
if (callback == null) return;
if (call.isCanceled()) return;
callback.onFailure(call, e);
}
});
}
}
使用则是一行代码,请求回调,适合MVC模式,MVP自己回调就好。
OKUtils.getInstance().post(url,jsonObject,new OkHttpCallback(new Subscriber<StoreManageBean>() {
@Override
public void onCompleted(StoreManageBean result) {
// result.toString();
}
@Override
public void onError(Throwable e) {
e.toString();
}
@Override
public Class<?> getType() {
return StoreManageBean.class;
}
}));
}
使用起来非常简单,逻辑也会很清晰。
资源下载地址:https://download.csdn.net/download/xjz123456qqq/12054325
本篇有啥问题的,请及时留言指出,欢迎指正,共同进步。
来源:CSDN
作者:FatFatWolf(胖胖狼)
链接:https://blog.csdn.net/xjz123456qqq/article/details/103714184