您的位置:首页 > 理论基础 > 计算机网络

项目中okhttp网络框架的封装使用

2017-10-11 10:58 387 查看
对okhttp网络框架进行封装,多种请求方式,包括图片上传,图片压缩上传,回调结果切换到主线程。使用fastjson将返回的json数据处理成对象返回。

1.工具类

/**
* Created by Pan on 2017/6/26 0026 09:54
* Desc:
*/

public class RequestManager {
//mdiatype 这个需要和服务端保持一致
private static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");
private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");
private static final String TAG = RequestManager.class.getSimpleName();
//请求接口根地址
private static final String BASE_URL = "http://xxxxxx/index.php?xxxxx=xxxx&xxxx";

private static volatile RequestManager mInstance;
/**
* get请求
*/
public static final int TYPE_GET = 0;
/**
* post请求参数为json
*/
public static final int TYPE_POST_JSON = 1;
/**
* post请求参数为表单
*/
public static final int TYPE_POST_FORM = 2;

private OkHttpClient mOkHttpClient;//okHttpClient 实例
private Handler okHttpHandler;//全局处理子线程和M主线程通信

/**
* 初始化RequestManager
*/
public RequestManager(Context context) {
//初始化OkHttpClient
mOkHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)//设置超时时间
.readTimeout(10, TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(10, TimeUnit.SECONDS)//设置写入超时时间
.build();
//初始化Handler
okHttpHandler = new Handler(context.getMainLooper());
}

/**
* 获取单例引用
*
* @return
*/
public static RequestManager getInstance(Context context) {
if (!AppData.NET_AVAILABLE) {
ToastUtils.showShort(context, context.getString(R.string.net_not_available));
}
RequestManager inst = mInstance;
if (inst == null) {
synchronized (RequestManager.class) {
inst = mInstance;
if (inst == null) {
inst = new RequestManager(context.getApplicationContext());
mInstance = inst;
}
}
}
return inst;
}

/**
* okHttp同步请求统一入口
*
* @param actionUrl   接口地址
* @param requestType 请求类型
* @param paramsMap   请求参数
*/
public void requestSyn(String actionUrl, int requestType, HashMap<String, String> paramsMap) {
switch (requestType) {
case TYPE_GET:
requestGetBySyn(actionUrl, paramsMap);
break;
case TYPE_POST_JSON:
requestPostBySyn(actionUrl, paramsMap);
break;
case TYPE_POST_FORM:
requestPostBySynWithForm(actionUrl, paramsMap);
break;
}
}

/**
* okHttp get同步请求
*
* @param actionUrl 接口地址
* @param paramsMap 请求参数
*/
private void requestGetBySyn(String actionUrl, HashMap<String, String> paramsMap) {
StringBuilder tempParams = new StringBuilder();
try {
//处理参数
int pos = 0;
for (String key : paramsMap.keySet()) {
if (pos > 0) {
tempParams.append("&");
}
//对参数进行URLEncoder
tempParams.append(String.format("%s=%s", key, URLEncoder.encode(paramsMap.get(key), "utf-8")));
pos++;
}
//补全请求地址
String requestUrl = String.format("%s/%s?%s", BASE_URL, actionUrl, tempParams.toString());
//创建一个请求
Request request = addHeaders().url(requestUrl).build();
//创建一个Call
final Call call = mOkHttpClient.newCall(request);
//执行请求
final Response response = call.execute();
response.body().string();
} catch (Exception e) {
LogUtil.e(TAG, e.toString());
}
}

/**
* okHttp post同步请求
*
* @param actionUrl 接口地址
* @param paramsMap 请求参数
*/
private void requestPostBySyn(String actionUrl, HashMap<String, String> paramsMap) {
try {
//处理参数
StringBuilder tempParams = new StringBuilder();
int pos = 0;
for (String key : paramsMap.keySet()) {
if (pos > 0) {
tempParams.append("&");
}
tempParams.append(String.format("%s=%s", key, URLEncoder.encode(paramsMap.get(key), "utf-8")));
pos++;
}
//补全请求地址
String requestUrl = String.format("%s/%s", BASE_URL, actionUrl);
//生成参数
String params = tempParams.toString();
//创建一个请求实体对象 RequestBody
RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, params);
//创建一个请求
final Request request = addHeaders().url(requestUrl).post(body).build();
//创建一个Call
final Call call = mOkHttpClient.newCall(request);
//执行请求
Response response = call.execute();
//请求执行成功
if (response.isSuccessful()) {
//获取返回数据 可以是String,bytes ,byteStream
LogUtil.e(TAG, "response ----->" + response.body().string());
}
} catch (Exception e) {
LogUtil.e(TAG, e.toString());
}
}

/**
* okHttp post同步请求表单提交
*
* @param actionUrl 接口地址
* @param paramsMap 请求参数
*/
private void requestPostBySynWithForm(String actionUrl, HashMap<String, String> paramsMap) {
try {
//创建一个FormBody.Builder
FormBody.Builder builder = new FormBody.Builder();
for (String key : paramsMap.keySet()) {
//追加表单信息
builder.add(key, paramsMap.get(key));
}
//生成表单实体对象
RequestBody formBody = builder.build();
//补全请求地址
String requestUrl = String.format("%s/%s", BASE_URL, actionUrl);

//创建一个请求
final Request request = addHeaders().url(requestUrl).post(formBody).build();
//创建一个Call
final Call call = mOkHttpClient.newCall(request);
//执行请求
Response response = call.execute();
if (response.isSuccessful()) {
LogUtil.e(TAG, "url: " + requestUrl + " response ----->" + response.body().string());
}
} catch (Exception e) {
LogUtil.e(TAG, e.toString());
}
}

/**
* okHttp异步请求统一入口
*
* @param actionUrl   接口地址
* @param requestType 请求类型
* @param paramsMap   请求参数
* @param callBack    请求返回数据回调
* @param <T>         数据泛型
**/
public <T> Call requestAsyn(String actionUrl, int requestType, HashMap<String, String> paramsMap, ReqCallBack<T> callBack) {
Call call = null;
switch (requestType) {
case TYPE_GET:
call = requestGetByAsyn(actionUrl, paramsMap, callBack);
break;
case TYPE_POST_JSON:
call = requestPostByAsyn(actionUrl, paramsMap, callBack);
break;
case TYPE_POST_FORM:
call = requestPostByAsynWithForm(actionUrl, paramsMap, callBack);
break;
}
return call;
}

/**
* okHttp get异步请求
*
* @param actionUrl 接口地址
* @param paramsMap 请求参数
* @param callBack  请求返回数据回调
* @param <T>       数据泛型
* @return
*/
private <T> Call requestGetByAsyn(String actionUrl, HashMap<String, String> paramsMap, final ReqCallBack<T> callBack) {
StringBuilder tempParams = new StringBuilder();
try {
int pos = 0;
for (String key : paramsMap.keySet()) {
if (pos > 0) {
tempParams.append("&");
}
tempParams.append(String.format("%s=%s", key, URLEncoder.encode(paramsMap.get(key), "utf-8")));
pos++;
}
final String requestUrl = String.format("%s=%s&%s", BASE_URL, actionUrl, tempParams.toString());
final Request request = addHeaders().url(requestUrl).build();
final Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
failedCallBack("访问失败", callBack);
LogUtil.e(TAG, e.toString());
}

@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String string = response.body().string();
LogUtil.e(TAG, "url: " + requestUrl + " response ----->" + string);
successCallBack(string, callBack);
} else {
failedCallBack("服务器错误", callBack);
}
}
});
return call;
} catch (Exception e) {
LogUtil.e(TAG, e.toString());
}
return null;
}

/**
* okHttp post异步请求
*
* @param actionUrl 接口地址
* @param paramsMap 请求参数
* @param callBack  请求返回数据回调
* @param <T>       数据泛型
* @return
*/
private <T> Call requestPostByAsyn(String actionUrl, HashMap<String, String> paramsMap, final ReqCallBack<T> callBack) {
try {
StringBuilder tempParams = new StringBuilder();
int pos = 0;
for (String key : paramsMap.keySet()) {
if (pos > 0) {
tempParams.append("&");
}
tempParams.append(String.format("%s=%s", key, URLEncoder.encode(paramsMap.get(key), "utf-8")));
pos++;
}
String params = tempParams.toString();
RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, params);
final String requestUrl = String.format("%s/%s", BASE_URL, actionUrl);
final Request request = addHeaders().url(requestUrl).post(body).build();
final Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
failedCallBack("访问失败", callBack);
LogUtil.e(TAG, e.toString());
}

@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String string = response.body().string();
LogUtil.e(TAG, "url: " + requestUrl + " response ----->" + string);
successCallBack(string, callBack);
} else {
failedCallBack("服务器错误", callBack);
}
}
});
return call;
} catch (Exception e) {
LogUtil.e(TAG, e.toString());
}
return null;
}

/**
* okHttp post异步请求表单提交
*
* @param actionUrl 接口地址
* @param paramsMap 请求参数
* @param callBack  请求返回数据回调
* @param <T>       数据泛型
* @return
*/
private <T> Call requestPostByAsynWithForm(String actionUrl, HashMap<String, String> paramsMap, final ReqCallBack<T> callBack) {
try {
FormBody.Builder builder = new FormBody.Builder();
for (String key : paramsMap.keySet()) {
builder.add(key, paramsMap.get(key));
}
RequestBody formBody = builder.build();
final String requestUrl = String.format("%s=%s", BASE_URL, actionUrl);
final Request request = addHeaders().url(requestUrl).post(formBody).build();
final Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
failedCallBack("访问失败", callBack);
LogUtil.e(TAG, e.toString());
}

@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String string = response.body().string();
LogUtil.e(TAG, "url: " + requestUrl + " response ----->" + string);
successCallBack(string, callBack);
} else {
failedCallBack("服务器错误", callBack);
}
}
});
return call;
} catch (Exception e) {
LogUtil.e(TAG, e.toString());
}
return null;
}

private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/jpg");

/**
* 像后台上传多张图片   type :1 用户头像上传 2 上传身份证  3 评论图片上传
*/
public <T> Call sendMutilImag(String actionUrl, int type, Map<String, String> params, String pic_key, List<File> files, final ReqCallBack<T> callBack) {
try {
MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder();
multipartBodyBuilder.setType(MultipartBody.FORM);
//遍历map中所有参数到builder
if (params != null) {
for (String key : params.keySet()) {
multipartBodyBuilder.addFormDataPart(key, params.get(key));
}
}
if (type == 1) { //
//遍历paths中所有图片绝对路径到builder,并约定key如“upload”作为后台接受多张图片的key
if (files != null) {
for (File file : files) {
multipartBodyBuilder.addFormDataPart(pic_key, file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file));
}
}
} else if (type == 2) { //身份证上传
//遍历paths中所有图片绝对路径到builder,并约定key如“upload”作为后台接受多张图片的key
if (files != null) {
for (int i = 0; i < files.size(); i++) {
File file = files.get(i);
LogUtil.i("addFormDataPart", i + "   filename : " + file.getName());
if (i == 0) {
multipartBodyBuilder.addFormDataPart("card_1", file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file));
} else if (i == 1) {
multipartBodyBuilder.addFormDataPart("card_2", file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file));
} else if (i == 2) {
multipartBodyBuilder.addFormDataPart("card_3", file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file));
}
}
}
} else if (type == 3) {
if (files != null) {
for (int i = 0; i < files.size(); i++) {
File file = files.get(i);
multipartBodyBuilder.addFormDataPart("imgs" + (i + 1), file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file));
LogUtil.i("filename", "filename: " + "key : " + "imgs0" + (i + 1) + "name: " + file.getName());
}
}
}

//构建请求体
RequestBody requestBody = multipartBodyBuilder.build();
Request.Builder RequestBuilder = new Request.Builder();

final String requestUrl = String.format("%s=%s", BASE_URL, actionUrl);

RequestBuilder.url(requestUrl);// 添加URL地址
RequestBuilder.post(requestBody);
Request request = RequestBuilder.build();
final Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
failedCallBack("访问失败", callBack);
}

@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String string = response.body().string();
LogUtil.e(TAG, "response ----->" + string);
successCallBack(string, callBack);
} else {
failedCallBack("服务器错误", callBack);
}
}
});
return call;
} catch (Exception e) {
LogUtil.e(TAG, e.toString());
}
return null;
}

public interface ReqCallBack<T> {
/**
* 响应成功
*/
void onReqSuccess(T result);

/**
* 响应失败
*/
void onReqFailed(String errorMsg);
}

/**
* 统一为请求添加头信息
*
* @return
*/
private Request.Builder addHeaders() {
Request.Builder builder = new Request.Builder()
.addHeader("Connection", "keep-alive")
.addHeader("platform", "2")
.addHeader("phoneModel", Build.MODEL)
.addHeader("systemVersion", Build.VERSION.RELEASE)
.addHeader("appVersion", "3.2.0");
return builder;
}

/**
* 统一同意处理成功信息
*
* @param result
* @param callBack
* @param <T>
*/
private <T> void successCallBack(final String result, final ReqCallBack<T> callBack) {
okHttpHandler.post(new Runnable() {
@Override
public void run() {
if (callBack != null) {
try {
TypeInfo typeInfo = ReqClassUtils.getCallbackGenericType(callBack.getClass());
callBack.onReqSuccess((T) ReqJsonUtils.parseHttpResult(typeInfo, result));
} catch (Exception e) {
LogUtil.e(TAG, e.toString());
}
}
}
});
}

/**
* 统一处理失败信息
*
* @param errorMsg
* @param callBack
* @param <T>
*/
private <T> void failedCallBack(final String errorMsg, final ReqCallBack<T> callBack) {
okHttpHandler.post(new Runnable() {
@Override
public void run() {
if (callBack != null) {
callBack.onReqFailed(errorMsg);
}
}
});
}
}


public class TypeInfo {
//Type泛型对象类型
private Class<?> componentType;
//Type所属对象类型
private Class<?> rawType;
//type
private Type type;

private TypeInfo(Class<?> rawType, Class<?> componentType) {

this.componentType = componentType;
this.rawType = rawType;
}

public static TypeInfo createArrayType(Class<?> componentType) {
return new TypeInfo(Array.class, componentType);
}

public static TypeInfo createNormalType(Class<?> componentType) {
return new TypeInfo(null, componentType);
}

public static TypeInfo createParameterizedType(Class<?> rawType, Class<?> componentType) {
return new TypeInfo(rawType, componentType);
}

public TypeInfo(Type type) {
this.type = type;
if (type instanceof ParameterizedType) {
//返回 Type 对象,表示声明此类型的类或接口。
this.rawType = (Class<?>) ((ParameterizedType) type).getRawType();
//getActualTypeArguments()返回表示此类型实际类型参数的 Type 对象的数组。
Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
this.componentType = (Class<?>) actualTypeArguments[0];
// typeReference=new TypeReference<Map<componentType,componentType>>(){};

} else if (type instanceof GenericArrayType) {
//返回 Type 对象,表示声明此类型的类或接口。
this.rawType = Array.class;
// 表示一种元素类型是参数化类型或者类型变量的数组类型
this.componentType = (Class<?>) ((GenericArrayType) type).getGenericComponentType();
} else {
this.componentType = (Class<?>) type;
}
}

public Type getType() {
return type;
}

public Class<?> getComponentType() {
return componentType;
}

public Class<?> getRawType() {
return rawType;
}

}


public class ReqClassUtils {

public static TypeInfo getCallbackGenericType(Class<?> clazz) {
//获得带有泛型的父类
Type genericSuperclass = clazz.getGenericSuperclass();//Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
TypeInfo type = getGetnericType(genericSuperclass);
if (type == null) {
Type[] genericInterfaces = clazz.getGenericInterfaces();
if (genericInterfaces != null && genericInterfaces.length > 0) {
type = getGetnericType(genericInterfaces[0]);
}
}
return type;
}

private static TypeInfo getGetnericType(Type type) {
if (type != null && type instanceof ParameterizedType) {
//getActualTypeArguments获取参数化类型的数组,泛型可能有多个
Type[] args = ((ParameterizedType) type).getActualTypeArguments();
if (args != null && args.length > 0) {
return new TypeInfo(args[0]);
}
}
return null;
}
}


public class ReqJsonUtils {

//基本类型映射关系Map
private static final Map primitiveWrapperTypeMap = new HashMap(8);

static {
//添加基本类型
primitiveWrapperTypeMap.put(Boolean.class, boolean.class);
primitiveWrapperTypeMap.put(Byte.class, byte.class);
primitiveWrapperTypeMap.put(Character.class, char.class);
primitiveWrapperTypeMap.put(Double.class, double.class);
primitiveWrapperTypeMap.put(Float.class, float.class);
primitiveWrapperTypeMap.put(Integer.class, int.class);
primitiveWrapperTypeMap.put(Long.class, long.class);
primitiveWrapperTypeMap.put(Short.class, short.class);
}

/**
* 将JSON字符串转换成指定的用户返回值类型
*
* @param type
* @param jsonData
* @return
*/
public static <T> T parseHttpResult(TypeInfo type, String jsonData) throws JSONException {
// 处理Void类型的返回值
if (Void.class.isAssignableFrom(type.getComponentType())) {
return null;
}
//获取当前type的数据类型
Class<?> rawType = type.getRawType();
//是否是Array
boolean isArray = rawType != null && Array.class.isAssignableFrom(rawType);
//是否是Collection
boolean isCollection = rawType != null && Collection.class.isAssignableFrom(rawType);
//是否是Map
boolean isMap = rawType != null && Map.class.isAssignableFrom(rawType);
//获取泛型类型
Class<?> componentType = type.getComponentType();
//声明结果对象
T result = null;
if (isCollection) {//处理collection
result = (T) JSON.parseArray(jsonData, componentType);
} else if (isArray) {//处理array
result = (T) JSON.parseArray(jsonData, componentType).toArray();
} else if (isMap) {//处理Map
result = (T) JSONObject.parseObject(jsonData, type.getType());
} else if (componentType.isAssignableFrom(String.class)) {//处理字符串返回值
return (T) jsonData;
} else {
// 接口的返回类型如果是简单类型,则会封装成为一个json对象,真正的对象存储在value属性上
if (isPrimitiveOrWrapper(componentType)) {
result = (T) parseObject(jsonData);
} else {
//处理自定义对象
result = (T) parseObject(jsonData, componentType);
}
}
return result;
}

/**
* 判断是否是基本数据类型
*
* @param clazz
* @return
*/
public static boolean isPrimitiveOrWrapper(Class clazz) {
return (clazz.isPrimitive() || isPrimitiveWrapper(clazz));
}

/**
* 判断是否是基本数据类型
*
* @param clazz
* @return
*/
public static boolean isPrimitiveWrapper(Class clazz) {
return primitiveWrapperTypeMap.containsKey(clazz);
}
}


2.图片压缩上传

使用Luban 压缩图片

compile ‘top.zibin:Luban:1.1.3’

Luban.with(this)
.load(mList)
.ignoreBy(100)
.setTargetDir(ImageCompressUtils.getPhotoCacheDir(mContext, "imag_thum").getAbsolutePath())
.setCompressListener(new OnCompressListener() {
@Override
public void onStart() {
}

@Override
public void onSuccess(File file) {
fileList.add(file);
try {
long fileSizes = getFileSizes(file);
String s = formetFileSize(fileSizes);
LogUtil.i("filename", "压缩后  ----》 图片路径: " + file.getAbsolutePath() + " 图片大小:" + s);

} catch (Exception e) {
e.printStackTrace();
}

if (fileList.size() == mList.size()) {
LogUtil.i("filename", "压缩完成,上传");
RequestManager.getInstance(GoodsCommentActivity.this).sendMutilImag(NetInterface.COMMENT_MSG, 3, params, "imgs", fileList, new RequestManager.ReqCallBack<CarResult>() {
@Override
public void onReqSuccess(CarResult result) {
if (loadingDialog.isShowing()) {
loadingDialog.dismiss();
}
ToastUtils.showShort(GoodsCommentActivity.this, result.msg);
if (result.code == 200) {
LogUtil.i("filename", "上传完成  --- ");
finish();
}
}

@Override
public void onReqFailed(String errorMsg) {
}
});

}
}

@Override
public void onError(Throwable e) {
}
}).launch();


public static long getFileSizes(File f) throws Exception {
long s = 0;
if (f.exists()) {
FileInputStream fis = null;
fis = new FileInputStream(f);
s = fis.available();
} else {
f.createNewFile();
}
return s;
}

/**
* 转换文件大小
*
* @param fileS
* @return
*/
public static String formetFileSize(long fileS) {
DecimalFormat df = new DecimalFormat("#.00");
String fileSizeString = "";
if (fileS < 1024) {
fileSizeString = df.format((double) fileS) + "B";
} else if (fileS < 1048576) {
fileSizeString = df.format((double) fileS / 1024) + "K";
} else if (fileS < 1073741824) {
fileSizeString = df.format((double) fileS / 1048576) + "M";
} else {
fileSizeString = df.format((double) fileS / 1073741824) + "G";
}
return fileSizeString;
}


上面就是我在项目中实践的结果,有好的建议指导可以留言。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐