关于设置OkGo⾃定义回调JsonCallback的相关整理基础通⽤版
1,通⽤的OkGo数据解析⽅法:
public abstract class JsonCallback<T>extends AbsCallback<T>{
private Type type;
private Class<T> clazz;
public JsonCallback(){
}
public JsonCallback(Type type){
}
public JsonCallback(Class<T> clazz){
this.clazz = clazz;
}
// convertResponse⽅法中定义的是Gson解析换换逻辑
@Override
error parse new
public T convertResponse(okhttp3.Response response)throws Throwable {
ResponseBody body = response.body();
if(body == null)return null;
T data = null;
Gson gson =new Gson();
JsonReader jsonReader =new JsonReader(body.charStream());
if(type != null){
data = gson.fromJson(jsonReader, type);
}else if(clazz != null){
data = gson.fromJson(jsonReader, clazz);
}else{
Type genType =getClass().getGenericSuperclass();
Type type =((ParameterizedType) genType).getActualTypeArguments()[0];
data = gson.fromJson(jsonReader, type);
}
return data;
}
}
上⾯的⽅法已经可以满⾜项⽬的需求了,可以⽤来直接转换类似如下的⼏种格式:
1,数据类型A-最外层数据类型是JsonObject,data 数据也是JsonObject
{
"code":0,
"msg":"请求成功",
"data":{
"id":123456,
"name":"张三",
"age":18
}
}
2,数据类型B-最外层数据类型是JsonObject,data 数据是JsonArray
{
"code":0,
"msg":"请求成功",
"data":[
{
"id":123456,
"name":"张三",
"age":18
},
{
"id":123456,
"name":"张三",
"age":18
},
{
"id":123456,
"name":"张三",
"age":18
}
]
}
3,数据类型C-没有固定的 msg、code 字段格式包装,服务器任意返回对象
"data":{
"id":123456,
"name":"张三",
"age":18
}
4,数据类型D-最外层数据类型是JsonArray,内部数据是JsonObject
[
{
"id":123456,
"name":"张三",
"age":18
},
{
"id":123456,
"name":"张三",
"age":18
},
{
"id":123456,
"name":"张三",
"age":18
}
]
使⽤⽅法如下(例如接⼝返回格式如上⾯的格式1):
1,根据返回值json结构定义对应的实体类
public class UserResponse {
public int code;
public String msg;
public User data;
}
2,执⾏OkGo⽹络请求:
OkGo.<UserResponse>get("wanandroid/banner/json")
.
tag(this)
.execute(new JsonCallback<UserResponse>(){
@Override
public void onSuccess(Response<UserResponse> response){
}
});
针对不同的数据返回格式,主要区别就是定义的实体类不⼀样,调⽤⽅法完全⼀致。
⾼端定制版
场景: ⼤多数情况,服务器返回的数据格式都是有个统⼀的规范的,就像上⾯的类型格式A和B那样(A和B也算统⼀规范,因为基础包装⼀致),那么我们可以使⽤泛型,分离基础包装与实际数据,这样⼦需要定义两个javabean,⼀个全项⽬通⽤的LzyResponse,⼀个单纯的业务模块需要的数据。
这种⽅法只适合服务器返回有固定数据格式的情况,如果服务器的数据格式不统⼀,不建议使⽤该种
⽅式。
⽐如通过和公司后台协商,统⼀了服务器端返回json的格式,如后台接⼝返回的数据格式只可能为如下两类:
{"code":"0","message":"success","data":{}}
{"code":"0","message":"success","data":[]}
我们真正需要的是data所包含的数据部分,如果继续按照通⽤版的⽅式来定义实体类则是这样的:
public class UserResponse {
public int code;
public String message;
public User data;
}
当使⽤其它接⼝的时候⼜得根据该接⼝返回的json字符串重新定义⼀个XXXResponse的实体类,并将data的类型改成XXX,如下:
public class Result<T>{
public int code;
public String message;
public T data;
}
很明显code,和message被重复定义了多次,显的有点重复,感觉不是很优雅,因此我们可以通过泛型将code和message字段抽取到⼀个全项⽬通⽤的LzyResponse的类中,这样我们只需要编写data字段所对应的实体类即可,更专注于我们的业务逻辑。如下:
public class LzyResponse<T>{
public int code;
public String message;
public T data;
}
那么对于data字段是User时则可以写为 Result< User > ,当是个列表的时候为 Result<List< User >>,其它同理。
优化的JsonCallback解析类如下:(需根据实际的项⽬进⾏修改,最下⾯的数据成功返回时的code,和对不同errcode的异常抛出)public abstract class JsonCallback2<T>extends AbsCallback<T>{
private Type type;
private Class<T> clazz;
public JsonCallback2(){
}
public JsonCallback2(Type type){
}
public JsonCallback2(Class<T> clazz){
this.clazz = clazz;
}
@Override
public T convertResponse(Response response)throws Throwable {
if(type == null){
if(clazz == null){
// 如果没有通过构造函数传进来,就⾃动解析⽗类泛型的真实类型(有局限性,继承后就⽆法解析到)                Type genType =getClass().getGenericSuperclass();
type =((ParameterizedType) genType).getActualTypeArguments()[0];
}else{
return parseClass(response, clazz);
}
}
if(type instanceof ParameterizedType){
return parseParameterizedType(response,(ParameterizedType) type);
}else if(type instanceof Class){
return parseClass(response,(Class<?>) type);
}else{
return parseType(response, type);
}
}
private T parseClass(Response response, Class<?> rawType)throws Exception {
if(rawType == null)return null;
ResponseBody body = response.body();
if(body == null)return null;
JsonReader jsonReader =new JsonReader(body.charStream());
if(rawType == String.class){
//noinspection unchecked
return(T) body.string();
}else if(rawType == JSONObject.class){
//noinspection unchecked
return(T)new JSONObject(body.string());
}else if(rawType == JSONArray.class){
//noinspection unchecked
return(T)new JSONArray(body.string());
}else{
T t = Convert.fromJson(jsonReader, rawType);
response.close();
return t;
}
}
private T parseType(Response response, Type type)throws Exception {
if(type == null)return null;
ResponseBody body = response.body();
if(body == null)return null;
JsonReader jsonReader =new JsonReader(body.charStream());
// 泛型格式如下: new JsonCallback<;任意JavaBean>(this)
T t = Convert.fromJson(jsonReader, type);
response.close();
return t;
}
private T parseParameterizedType(Response response, ParameterizedType type)throws Exception { if(type == null)return null;
ResponseBody body = response.body();
if(body == null)return null;
JsonReader jsonReader =new JsonReader(body.charStream());
JsonReader jsonReader =new JsonReader(body.charStream());
Type rawType = RawType();// 泛型的实际类型
Type typeArgument = ActualTypeArguments()[0];// 泛型的参数
if(rawType != LzyResponse.class){
// 泛型格式如下: new JsonCallback<;外层BaseBean<;内层JavaBean>>(this)
T t = Convert.fromJson(jsonReader, type);
response.close();
return t;
}else{
if(typeArgument == Void.class){
// 泛型格式如下: new JsonCallback<LzyResponse<Void>>(this)
SimpleResponse simpleResponse = Convert.fromJson(jsonReader, SimpleResponse.class);
response.close();
//noinspection unchecked
return(T) LzyResponse();
}else{
// 泛型格式如下: new JsonCallback<LzyResponse<;内层JavaBean>>(this)
LzyResponse lzyResponse = Convert.fromJson(jsonReader, type);
response.close();
int code = Code;
/
/ ⼀般来说服务器会和客户端约定⼀个数表⽰成功,如200,其余的表⽰失败,如400,300等,这⾥根据实际情况罗列并抛出if(code ==0){
//noinspection unchecked
return(T) lzyResponse;
}else if(code ==400){
throw new IllegalStateException("Token已过期");
}else if(code ==300){
throw new IllegalStateException("⽤户名密码错误");
}else{
// 直接将服务端的错误信息抛出,onError中可以获取
throw new IllegalStateException("错误代码:"+ code +",错误信息:"+ Msg);
}
}
}
}
}
其中需要⽤到的Convert类如下:(该类不⽤修改)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。