一、Xutils 3.0简介
xUtils是目前功能比较完善的一个
Android
开源框架,最近又发布了xUtil3.0,在增加新功能的同时又提高了框架的性能,下面来看看官方(
https://github.com/wyouflf/xUtils3
)对xUtils3的介绍:
- xUtils包含了很多实用的android工具;
- xUtils支持超大文件(超过2G)上传,更全面的http请求协议支持(11种谓词),拥有更加灵活的ORM,更多的事件注解支持且不受混淆影响;
- xUtils 最低兼容Android 4.0 (api level 14);
- xUtils3变化较多所以建立了新的项目不在旧版(github.com/wyouflf/xUtils)上继续维护, 相对于旧版本:
-
- HTTP实现替换HttpClient为UrlConnection, 自动解析回调泛型, 更安全的断点续传策略;
- 支持标准的Cookie策略, 区分domain, path;
- 事件注解去除不常用的功能, 提高性能;
- 数据库api简化提高性能, 达到和greenDao一致的性能;
- 图片绑定支持gif(受系统兼容性影响, 部分gif文件只能静态显示), webp; 支持圆角, 圆形, 方形等裁剪, 支持自动旋转。
二、Xutils引入和初始化(基于AS)
1.build.gradle文件配置
2.Application里进行初始化
x.Ext.init(this);
3、框架封装
public class NetRequestUtil {
private volatile static NetRequestUtil instance;/**
* Double Check 单例模式
*
* @return
*/
public static NetRequestUtil getInstance() {
if (instance == null) {
synchronized (NetRequestUtil.class) {
if (instance == null) {
instance = new NetRequestUtil();
}
}
}
return instance;
}
/**
* /appLogin','/version','/applogout','/weekReportDel','/idcode','/islogin','/losepwd'
* 不需要传token
*/
public static final int REQUEST_TOKEN = 0;// 默认需要token
public static final int REQUEST_NO_TOKEN = 1; // 在登录等几个特殊接口不需要token
public static final int REQUEST_METHOD_GET = 0;// get请求
public static final int REQUEST_METHOD_POST = 1; // post请求
/**
* 基地址
*/
private String TestUrl = "http://a.http.cn/"; // 测试环境
private String BaseUrl = TestUrl;
/**
* 接口地址
*/
/ 登录 退出 /
public String LOGIN = "appLogin"; // 登录接口
public String LOGOUT = "applogout"; // 退出
public String IS_LOGIN = "islogin"; // 每次判断是否要重新登录,有效期内不需要每次登录
/**
* 取得完整地址
*
* @param apiUrl
* @return
*/
public String getUrl(String apiUrl) {
return BaseUrl + apiUrl;
}
/**
* 取得公共参数
*
* @return
*/
public Map<String, Object> getBaseMap() {
Map<String, Object> map = new HashMap<>();
// 添加公参
map.put("device_token", Tools.getDeviceId(MyApplication.getInstance())); // 设备唯一标识
map.put("device_uuid", Tools.getDeviceId(MyApplication.getInstance()));
map.put("appid", "android");
map.put("version", Tools.getVersion(MyApplication.getInstance()));
if (EmptyUtils.isNotEmpty(MyApplication.getInstance().getUser())
&& EmptyUtils.isNotEmpty(MyApplication.getInstance().getUser().getData().getUsername())) {
map.put("username", MyApplication.getInstance().getUser().getData().getUsername());
}
return map;
}
/**
* 异步get请求
*
* @param url
* @param maps
* @param requestCode
* @param clazz
* @param listener
* @return
*/
public Callback.Cancelable get(String url, Map<String, String> maps, final int requestCode,
final Class<? extends MResponse> clazz, final NetResponseListener listener) {
if (!NetworkUtils.isConnected()) {
ToastU.showShortToast(R.string.no_network);
}
maps.put("sign", Tools.getSign(maps)); // MD5加密
RequestParams params = new RequestParams(url);
if (maps != null && !maps.isEmpty()) {
for (Map.Entry<String, String> entry : maps.entrySet()) {
params.addQueryStringParameter(entry.getKey(), entry.getValue());
}
}
Callback.Cancelable cancelable = x.http().get(params, new Callback.CommonCallback<String>() {
@Override
public void onSuccess(String result) {
MResponse mResponse = GsonUtil.processJS(result, clazz); //按正常响应解析
listener.onSuccess(mResponse, requestCode, result);
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
listener.onError(ex, isOnCallback, requestCode);
}
@Override
public void onCancelled(CancelledException cex) {
listener.onCancelled(cex);
}
@Override
public void onFinished() {
listener.onFinish();
}
});
return cancelable;
}
/**
* 带缓存的异步get请求
*
* @param url
* @param maps
* @param requestCode
* @param clazz
* @param listener
* @return
*/
public Callback.Cancelable getCache(String url, Map<String, String> maps, final int requestCode,
final Class<? extends MResponse> clazz, final NetResponseListener listener) {
if (!NetworkUtils.isConnected()) {
ToastU.showShortToast(R.string.no_network);
}
maps.put("sign", Tools.getSign(maps)); // MD5加密
RequestParams params = new RequestParams(url);
if (maps != null && !maps.isEmpty()) {
for (Map.Entry<String, String> entry : maps.entrySet()) {
params.addQueryStringParameter(entry.getKey(), entry.getValue());
}
}
// 默认缓存存活时间, 单位:毫秒(如果服务器没有返回有效的max-age或Expires则参考)
params.setCacheMaxAge(1000 * 60);//设置缓存当这个缓存事件过了的时候, 这时候就会不走这个onCache方法, 直接发起网络请求,
Callback.Cancelable cancelable = x.http().get(params, new Callback.CacheCallback<String>() {
@Override
public boolean onCache(String result) {
MResponse mResponse = GsonUtil.processJS(result, clazz);//按正常响应解析
listener.onSuccess(mResponse, requestCode, result);
return true;//这里返回一个true, 就是走了cache就不再发起网络请求了, 返回一个false, 就是不信任缓存数据, 再次发起网络请求
}
@Override
public void onSuccess(String result) {
if (result != null) {
//如果走了cache方法返回了true, 将不再发起网络请求, 这里拿到的result就是null,
MResponse mResponse = GsonUtil.processJS(result, clazz);//按正常响应解析
listener.onSuccess(mResponse, requestCode, result);
}
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
listener.onError(ex, isOnCallback, requestCode);
}
@Override
public void onCancelled(CancelledException cex) {
listener.onCancelled(cex);
}
@Override
public void onFinished() {
listener.onFinish();
}
});
return cancelable;
}
/**
* 异步post请求,去除请求标志,默认为0
*
* @param url
* @param maps
* @param clazz
* @param listener
* @return
*/
public Callback.Cancelable post(Context context, String url, Map<String, Object> maps,
final Class<? extends MResponse> clazz, final NetResponseListener listener) {
return post(context, url, maps, REQUEST_TOKEN, clazz, listener);
}
/**
* 异步post请求
*
* @param context
* @param url
* @param maps
* @param requestCode
* @param clazz
* @param listener
* @return
*/
public Callback.Cancelable post(final Context context, String url, Map<String, Object> maps,
final int requestCode, final Class<? extends MResponse> clazz,
final NetResponseListener listener) {
if (!NetworkUtils.isConnected()) {
ToastU.showShortToast(R.string.no_network);
}
if (requestCode == REQUEST_TOKEN) {
maps.put("token", MyApplication.getInstance().getUser().getData().getToken()); // 添加token
}
maps.put("sign", Tools.getSign(maps)); // MD5加密
RequestParams params = new RequestParams(url);
params.setReadTimeout(30 * 1000); // 设置网络超时时间
params.setConnectTimeout(30 * 1000);
params.setMethod(HttpMethod.POST);
if (!maps.isEmpty()) {
for (Map.Entry<String, Object> entry : maps.entrySet()) {
params.addParameter(entry.getKey(), entry.getValue());
}
}
AppLog.i(Const.HTTP_LOG_KEY, "=======http-request-url::::::" + url);
AppLog.i(Const.HTTP_LOG_KEY, "=======http-request-parameters::::::" + params.toString());
//为了防止app登录成功以后im当时的登录失败,每次访问接口的时候判断一下是否需要im失败,如果失败就进行重新登录
if (!IMUseHelper.isImLogin()) {
IMUseHelper.initImLogin();
}
final Callback.Cancelable post = x.http().post(params, new Callback.CommonCallback<String>() {
@Override
public void onSuccess(final String result) {
try {
JSONObject jsonObject = new JSONObject(result);
// 1. 判断为token过期则重新去登录,比如在其他设备上登录 2.人员角色变化,需要重新登录更新个人信息
if (jsonObject.getInt("code") == Const.LOGIN_OUT_TIME
|| Const.ROLE_CHANGES == jsonObject.getInt("code")) {
if (!TextUtils.isEmpty(jsonObject.getString("message"))) {ToastU.showLongToast(jsonObject.getString("message"));
}
Tools.logout(context);
} else {
final MResponse mResponse = GsonUtil.processJS(result, clazz);//按正常响应解析
listener.onSuccess(mResponse, requestCode, result);
}
} catch (JSONException e) {
e.printStackTrace();
}
AppLog.i(Const.HTTP_LOG_KEY, "=======---onSuccess---======:" + result);
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
if (ex instanceof HttpException) { // 网络错误
HttpException httpEx = (HttpException) ex;
int responseCode = httpEx.getCode();
String responseMsg = httpEx.getMessage();
String errorResult = httpEx.getResult();
AppLog.i(Const.HTTP_LOG_KEY, "=======---onError---网络错误======:"
+ "返回码:" + responseCode
+ ";---错误信息:" + responseMsg
+ ";---错误结果:" + errorResult);
} else { // 其他错误
listener.onError(ex, isOnCallback, requestCode);
AppLog.i(Const.HTTP_LOG_KEY, "=======---onError---其他错误======:" + ex.toString());
}
}
@Overridepublic void onCancelled(CancelledException cex) {
listener.onCancelled(cex);
AppLog.i(Const.HTTP_LOG_KEY, "=======---onCancelled---======:" + cex.toString());
}
// 不管成功或者失败最后都会回调该接口
@Override
public void onFinished() {
listener.onFinish();
AppLog.i(Const.HTTP_LOG_KEY, "=======---onFinished---======:" + clazz);
}
});
return post;
}
/**
* 普通异步网络请求 get或者post
*
* @param context
* @param url
* @param maps
* @param requestCode
* @param requestMethod
* @param clazz
* @param listener
* @return
*/
public Callback.Cancelable httpRequest(final Context context, String url,
Map<String, Object> maps,
final int requestCode, int requestMethod,
final Class<? extends MResponse> clazz,
final NetResponseListener listener) {
HttpMethod method = null; // 请求方式
if (requestMethod == REQUEST_METHOD_GET) {
method = HttpMethod.GET;
} else {
method = HttpMethod.POST;
}
// token 添加
if (requestCode == REQUEST_TOKEN) {
maps.put("token", MyApplication.getInstance().getUser().getData().getToken()); // 添加token
}
maps.put("sign", Tools.getSign(maps)); // MD5加密
RequestParams params = new RequestParams(url);
if (!maps.isEmpty()) {
for (Map.Entry<String, Object> entry : maps.entrySet()) {
params.addBodyParameter(entry.getKey(), entry.getValue().toString());
}
}
Callback.Cancelable request = x.http().request(method, params, new Callback.CommonCallback<String>() {
@Override
public void onSuccess(String result) {
try {
JSONObject jsonObject = new JSONObject(result);
if (jsonObject.getInt("code") == Const.LOGIN_OUT_TIME) { // 判断为token过期则重新去登录
ToastU.showLongToast(jsonObject.getString("message"));
Tools.logout(context);
} else {
final MResponse mResponse = GsonUtil.processJS(result, clazz);//按正常响应解析
listener.onSuccess(mResponse, requestCode, result);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
@Overridepublic void onError(Throwable ex, boolean isOnCallback) {
if (ex instanceof HttpException) { // 网络错误
HttpException httpEx = (HttpException) ex;
int responseCode = httpEx.getCode();
String responseMsg = httpEx.getMessage();
String errorResult = httpEx.getResult();
AppLog.i(Const.HTTP_LOG_KEY, "=======---onError---网络错误======:"
+ "返回码:" + responseCode
+ ";---错误信息:" + responseMsg
+ ";---错误结果:" + errorResult);
} else { // 其他错误
listener.onError(ex, isOnCallback, requestCode);
AppLog.i(Const.HTTP_LOG_KEY, "=======---onError---其他错误======:" + ex.toString());
}
}
@Override
public void onCancelled(CancelledException cex) {
listener.onCancelled(cex);
AppLog.i(Const.HTTP_LOG_KEY, "=======---onCancelled---======:" + cex.toString());
}
@Override
public void onFinished() {
listener.onFinish();
AppLog.i(Const.HTTP_LOG_KEY, "=======---onFinished---======:" + clazz);
}
});
return request;
}
/**
* 文件上传
*
* @param url
* @param maps
* @param file
* @param requestCode
* @param clazz
* @param listener
* @return
*/
public Callback.Cancelable upLoadFile(String url, Map<String, String> maps, Map<String, File> file,
final int requestCode, final Class<? extends MResponse> clazz,
final NetUpLoadFileListener listener) {
if (!NetworkUtils.isConnected()) {
ToastU.showShortToast(R.string.no_network);
}
// token 添加
if (requestCode == REQUEST_TOKEN) {
maps.put("token", MyApplication.getInstance().getUser().getData().getToken()); // 添加token
}
maps.put("sign", Tools.getSign(maps)); // MD5加密
RequestParams params = new RequestParams(url);
params.setMethod(HttpMethod.POST);
if (!maps.isEmpty()) {
for (Map.Entry<String, String> entry : maps.entrySet()) {
params.addBodyParameter(entry.getKey(), entry.getValue());
}
}
if (file != null && !maps.isEmpty()) {
for (Map.Entry<String, File> entry : file.entrySet()) {
params.addBodyParameter(entry.getKey(), entry.getValue().getAbsoluteFile());
}
}
AppLog.i(Const.HTTP_LOG_KEY, "=======http-request-url::::::" + url);
AppLog.i(Const.HTTP_LOG_KEY, "=======http-request-parameters::::::" + params.toString());
// 有上传文件时使用multipart表单, 否则上传原始文件流.
params.setMultipart(true);//这个是标示上传的文件内容的,
Callback.Cancelable upLoad = x.http().post(params, new Callback.ProgressCallback<String>() {
@Override
public void onSuccess(String result) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(result);
ToastU.showLongToast(jsonObject.getString("message"));
} catch (JSONException e) {
e.printStackTrace();
}
MResponse mResponse = GsonUtil.processJS(result, clazz);//按正常响应解析
listener.onSuccess(mResponse, requestCode, result);
AppLog.i(Const.HTTP_LOG_KEY, "=======---onSuccess---======:" + result);
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
listener.onError(ex, isOnCallback, requestCode);
AppLog.i(Const.HTTP_LOG_KEY, "=======---onError---======:" + ex.toString());
}
@Override
public void onCancelled(CancelledException cex) {
listener.onCancelled(cex);
AppLog.i(Const.HTTP_LOG_KEY, "=======---onCancelled---======:" + cex.toString());
}
@Override
public void onFinished() {
listener.onFinish();
AppLog.i(Const.HTTP_LOG_KEY, "=======---onFinished---======:");
}
@Override
public void onWaiting() {
listener.onWaiting();
AppLog.i(Const.HTTP_LOG_KEY, "=======---onWaiting---======:");
}
@Override
public void onStarted() {
listener.onStarted();
AppLog.i(Const.HTTP_LOG_KEY, "=======---onStarted---======:");
}
@Override
public void onLoading(long total, long current, boolean isDownloading) {
listener.onLoading(current, isDownloading, requestCode);
AppLog.i(Const.HTTP_LOG_KEY, "=======---onLoading---======:"
+ "total:" + total + "---current:"
+ current + "---isDownloading:"
+ isDownloading);
}
});
return upLoad;
}
/**
* 文件下载
*
* @param url
* @param filepath
* @param requestCode
* @param listener
*/
public void downLoadFile(String url, String filepath, final int requestCode, final NetDownLoadFileListener listener) {
if (!NetworkUtils.isConnected()) {
ToastU.showShortToast(R.string.no_network);
}
RequestParams params = new RequestParams(url);
params.setAutoRename(true);// 断点续传, 也就是说支持中断之后再继续下载,
params.setSaveFilePath(filepath);//设置文件保存的路径
x.http().post(params, new Callback.ProgressCallback<File>() {
@Override
public void onSuccess(final File result) {
listener.onSuccess(result, requestCode);
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
listener.onError(ex, isOnCallback, requestCode);
}
@Override
public void onCancelled(CancelledException cex) {
listener.onCancelled(cex);
}
@Override
public void onFinished() {
listener.onFinish();
}
@Override
public void onWaiting() {
listener.onWaiting();
}
@Override
public void onStarted() {
listener.onStarted();
}
@Override
public void onLoading(final long total, final long current, final boolean isDownloading) {
listener.onLoading(current, isDownloading, requestCode);
}
});
}
}