背景
以下面服务器返回数据格式为例:
{
"code":200,
"msg":"成功",
"data":{
"userName":"小明",
"nickName":"一花一世界"
}
}
在这个返回的JSON
数据里面code
和msg
的类型是固定不变的,但是data
的类型却会经常改变。比如这里返回的是User
格式的数据,另一个接口返回的可能就是UserInfo
格式的数据了。由于各个接口返回的数据格式不同,如果对应的每个接口都进行GSON
解析,那么我们的代码将会显得比较臃肿。此时如果有一个统一的封装接口来处理解析返回的数据,不仅会避免大量冗余代码的出现,同时将会大大地提高开发效率。
创建接口返回实体类
public class HttpResult<T> {
private T data;
private int code;
private String msg;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return "ServerCallBackModel{" +
"data=" + data +
", code=" + code +
", msg='" + msg + '\'' +
'}';
}
}
封装服务器回调接口
1、回调的抽象基类
public abstract class HttpCallBack<T> {
private Type mGenericSuperclass;
public HttpCallBack() {
Type genericSuperclass = getClass().getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
mGenericSuperclass = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
} else {
mGenericSuperclass = Object.class;
}
}
public abstract void onResolve(T t);
public abstract void onFailed(int code, String msg);
public Type getType() {
return mGenericSuperclass;
}
}
Type
:Java
中所有类型的公共高级接口。包括原始类型(对应Class
)、参数化类型(对应ParameterizedType
)、数组类型(对应GenericArrayType
)、类型变量(对应TypeVariable
)和基本类型(对应Class
)。getGenericSuperclass()
:获得带有泛型的父类。ParameterizedType
:参数化类型,即泛型。getActualTypeArguments()
:获取参数化类型的数组,泛型参数可能有多个。
getActualTypeArguments()[0]
得到泛型的第一个参数T
的类型,赋值给当前泛型类型的成员变量genericSuperclass
。如果不是参数化类型,比如在接收服务器回调的地方没有加泛型类型,那么我们就给genericSuperclass
赋值Object
的Class
对象。
其中的抽象方法:
onResolve()
:用来解析接口返回的json
数据,在子类中需要重写它来进行具体解析。
onFailed()
:错误回调。
2、解析返回数据的抽象子类
public abstract class OnServerCallBack<T, V> extends HttpCallBack<T> {
@Override
public void onResolve(T t) {
if (t instanceof HttpResult) {
HttpResult<V> callbackData = (HttpResult) t;
V result = callbackData.getData();
if (callbackData.getCode() == 200) {
onSuccess(result);
} else {
onFailed(callbackData.getCode(), callbackData.getMsg());
}
} else {
onSuccess((V) t);
}
}
@Override
public void onFailed(int code, String msg) {
if (enableShowToast()) {
ToastUtil.showText(msg);
} else {
onFailure(code, msg);
}
}
public abstract void onSuccess(V data);
public abstract void onFailure(int code, String msg);
public boolean enableShowToast() {
return false;
}
}
这里我们定义了一个抽象带两个类型参数的泛型类,第一个参数是Gson
映射的外层对象,比如可以传入我们前面定义的HttpResult
;第二个参数就是外层对象中的数据了,比如HttpResult
中的data
。
其中enableShowToast()
这个方法主要是用于拦截错误返回,用于统一处理所有请求的错误,默认只判断是否需要直接弹Toast
显示错误信息。如果想直接将错误信息弹窗提示,只需要重写enableShowToast
方法,返回true
即可。
3、不解析返回数据的抽象子类
public abstract class OnCommonCallBack<T> extends HttpCallBack<T> {
@Override
public void onResolve(T t) {
onSuccess(t);
}
@Override
public void onFailed(int code, String msg) {
if (enableShowToast()) {
ToastUtil.showText(msg);
} else {
onFailure(code, msg);
}
}
public abstract void onSuccess(T data);
public abstract void onFailure(int code, String msg);
public boolean enableShowToast() {
return false;
}
}
此泛型类用于直接返回Http
返回的数据。有些时候我们不需要对Http
返回的数据进行解析,这时我们就可以使用此种解析方式来解析。
Gson解析
public class HttpUtils {
private static Gson mGson;
public static void getRequest(String url, Map<String, String> params, HttpCallBack callBack) {
if (callBack == null) {
return;
}
if (mGson == null) {
mGson = new Gson();
}
boolean returnJson = false;
Type type = callBack.getType();
if (type instanceof Class) {
switch (((Class) type).getSimpleName()) {
case "Object":
case "String":
returnJson = true;
break;
default:
break;
}
}
if (returnJson) {
try {
callBack.onResolve(url);
} catch (Exception e) {
callBack.onFailed(-1, e.getMessage());
e.printStackTrace();
}
} else {
try {
callBack.onResolve(mGson.fromJson(url, type));
} catch (Exception e) {
callBack.onFailed(-1, e.getMessage());
e.printStackTrace();
}
}
}
}
在Http
请求成功返回数据之后,首先判断泛型类型type
是不是Class
类型,如果是则判断type
的名字是否为String
或者Object
,是则直接在成功回调中传入返回的json
字符串。如果不是则用Gson
将json
数据解析出来,实参就是type
。
使用
//解析Http返回的Json数据,返回data字段中封装的内容
showModel.ShowUser(Constant.object1, null, new OnServerCallBack<HttpResult<User>, User>() {
@Override
public void onSuccess(User data) {
LogUtil.e("ShowUser-->" + data.toString());
}
@Override
public void onFailure(int code, String msg) {
LogUtil.e("ShowUser failure-->" + code + " : " + msg);
}
});
//不解析Http返回的Json数据,返回Http返回的内容
showModel.ShowStringData(Constant.object1, null, new OnCommonCallBack<String>() {
@Override
public void onSuccess(String data) {
LogUtil.e("ShowStringData-->" + data);
}
@Override
public void onFailure(int code, String msg) {
LogUtil.e("ShowStringData failure-->" + code + " : " + msg);
}
});
至此我们就可以按需解析服务器返回的数据了。
项目地址 ☞ 传送门