OkHttp相信都不陌生了,Android一个很好用的网络请求框架,GitHub上面2w多个Start,Square公司出品,也是JakeWharton大神的代表作之一(JakeWharton大神已离开Square公司加入Google),此处膜拜大神三秒钟……
我自己根据项目需要二次封装了OkHttp,因为和后台哥们商量的是,所有的参数全部转为Json传给服务器。上传图片时,把图片转换成Base64字符串,同样以Json的格式上传到服务器。
这是我用到的第三方依赖:
compile 'com.squareup.okhttp3:okhttp:3.8.1' //OkHttp的依赖,可能不是最新版本,可以去GitHub找最新的OkHttp依赖
compile 'id.zelory:compressor:2.0.0' //图片压缩,压缩效率和速度都不错
首先,创建一个OkHttp的单例类。在使用OkHttp时,最好保证全局只有一个OkHttpClient对象,这样方便管理和配置整个应用的网络请求的超时时间、缓存等等。如果有某个特殊的网络请求需要我们特别处理,我们也可以clone一个OkHttpClient对象单独处理。
public class OkHttpClientInstance {
public static OkHttpClient instance;
private OkHttpClientInstance() {}
public static OkHttpClient getInstance() {
if (instance == null) {
synchronized (OkHttpClientInstance.class) {
if (instance == null) {
//配置了网络请求的超时时间
instance = new OkHttpClient().newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.build();
}
}
}
return instance;
}
}
创建网络请求类Network
public class Network {
//上下文
private Context mContext;
//请求的url
private String mUrl;
//通过单例类得到的OkHttpClient 对象
private OkHttpClient mClient;
//解析服务器返回数据的Gson
private Gson mGson;
private Handler mHandler;
//登录之后返回的Token字符串
private String mToken;
public Network(Context context, String url) {
this.mContext = context;
this.mUrl = url;
mClient = OkHttpClientInstance.getInstance();
mGson = new Gson();
mHandler = new Handler();
//获取Token的方式可以在进入程序时获取,存为全局变量
mToken = SPUtil.getString(context, SPUtil.LOGIN_TOKEN, "");
}
/**
* 执行普通的post请求,参数集合全部转为json
*
* @param map 传入的参数集合
* @param netCallBack 回调接口
*/
public void performPost(Map<Object, Object> map, final NetCallBack netCallBack) {
String params = mGson.toJson(map);
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, params);
final Request request = new Request.Builder()
.url(mUrl)
.addHeader("Authorization", "Bearer" + mToken)
.post(body)
.build();
mClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
doFailure(netCallBack);
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
doResponse(response, netCallBack);
}
});
}
/**
* post上传图片,全部转为json上传
*
* @param params 参数集合
* @param picturePathList 图片的路径集合
* @param netCallBack 回调接口
*/
public void upLoadPicture(Map<Object, Object> params, List<String> picturePathList, final NetCallBack netCallBack) {
List<PictureFileBean> fileList = new ArrayList<>();
//处理图片
for (int i = 0; i < picturePathList.size(); i++) {
File file = new File(picturePathList.get(i));
PictureFileBean fileBean = new PictureFileBean();
try {
//压缩图片
File compressedFile = new Compressor(mContext).compressToFile(file);
//把图片转为base64
String base64String = ImageToBase64.GetImageStr(compressedFile);
//拼接图片集合
fileBean.setPicFile(base64String);
fileBean.setPicType("JPEG");
fileList.add(fileBean);
} catch (IOException e) {
e.printStackTrace();
}
}
params.put("file", fileList);
String json = mGson.toJson(params);
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody requestBody = RequestBody.create(JSON, json);
final Request request = new Request.Builder()
.url(mUrl)
.addHeader("Authorization", "Bearer" + mToken)
.post(requestBody)
.build();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
doFailure(netCallBack);
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
doResponse(response, netCallBack);
}
});
}
}, 200);
}
/**
* 处理失败
*
* @param netCallBack
*/
private void doFailure(final NetCallBack netCallBack) {
mHandler.post(new Runnable() {
@Override
public void run() {
netCallBack.onNetFailure();
}
});
}
/**
* 处理成功
*
* @param response
* @param netCallBack
* @throws IOException
*/
private void doResponse(Response response, final NetCallBack netCallBack) throws IOException {
final String result = response.body().string();
if (!TextUtils.isEmpty(result)) {
try {
JSONObject jsonObject = new JSONObject(result);
String success = jsonObject.getString("success");
if ("true".equals(success)) {
mHandler.post(new Runnable() {
@Override
public void run() {
netCallBack.onSuccess(result);
}
});
} else if ("false".equals(success)) {
mHandler.post(new Runnable() {
@Override
public void run() {
netCallBack.onError(result);
}
});
}
} catch (JSONException e) {
e.printStackTrace();
mHandler.post(new Runnable() {
@Override
public void run() {
//服务器返回错误
netCallBack.onError(result);
}
});
}
}
}
/**
* 回调接口
*/
public interface NetCallBack {
//网络请求失败,没连网
void onNetFailure();
//网络请求成功
void onSuccess(String result);
//网络请求成功,后台服务器有误
void onError(String result, String errorMessage);
}
}
我创建了一个内部接口类,用于处理网络请求结果的回调。里面有三个方法:
- onNetFailure()方法用于处理网络请求失败,没有联网的情况;
- onSuccess()方法用于处理网络请求成功的回调;
- onError()方法用于处理后台服务器返回错误的情况,通常可以结合错误码来更加规范的处理该结果 。
图片转Base64的方法
public class ImageToBase64 {
/**
* 图片转换成base64
* @param file
* @return
*/
public static String GetImageStr(File file) {
Bitmap bitmap = BitmapFactory.decodeFile(file.getPath());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);//参数100表示不压缩
byte[] bytes = bos.toByteArray();
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
return Base64.encodeToString(bytes, Base64.DEFAULT);
}
}
关于调用,你可以在Activity里面直接调用Network网络层的方法,但是我不推荐你这样做。开发过程中基于高内聚、低耦合的原则,可以再写一个类,里面封装具体业务的请求方法,提供给Activity调用。
public class ActivityNet {
private Context mContext;
public AbnormalHandleActivityNet(Context context) {
mContext = context;
}
/**
* 确认处理异常点击事件
*
* @param guid
* @param abnormalCount
* @param abnormalTypePosition
* @param abnormalRemark
* @param parentGuid
* @param picturePathList
*/
public void btnConfirmHandle(String guid, String abnormalCount, int abnormalTypePosition, String abnormalRemark, String parentGuid, ArrayList<String> picturePathList, Network.NetCallBack netCallBack) {
String url = UrlUtil.getUrl("tms.app.order.backed.backExSubmit");
Map<Object, Object> params = new HashMap<>();
params.put("guid", guid);
params.put("exceptionQty", abnormalCount);
params.put("exceptionType", abnormalTypePosition);
params.put("exceptionMemo", abnormalRemark);
params.put("parentGuid", parentGuid);
Network network = new Network(mContext, url);
network.upLoadPicture(params, picturePathList, netCallBack);
}
}
这是一个复杂的调用的方法,既需要上传参数,也需要上传图片。参数都是以键值对的方式添加进Map集合的,每个键的含义,是和后台哥们商量好的,接口文档里面都有。
picturePathList是一个图片路径的集合。我们可能会同时上传多张图片,得到多张图片的路径后,就构建成一个集合。
这个类里面是具体业务的网络请求方法,我们在Activity中直接调用这个类里面的方法。Activity可以通过实现Network.NetCallBack接口来处理结果并作出相应的UI更新。
希望能帮到你。