上两篇文章主要讲述寻找问题根源到解决思路,解决办法比较复杂,这里提供一种最简单的解决办法,不需要改动太多的东西:
比如一般后台返回的数据格式如下:
正常数据
{"code":200,"data":{"id":"adsd","name":"Weipru"},"msg":"success","timeStamp":"20191015102953"}
不存在data的数据
{"code":1000,"data":"","msg":"请登录!","timeStamp":"20191014094718"}
对应我们自己的Http响应实体
public class HttpMessage<T> {
private int code;
private T data;
private String msg;
private String timeStamp;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getTimeStamp() {
return timeStamp;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}
}
正常访问后台流程
- 后台API
public interface GsonTestAPI {
@GET("/user/list")
Call<HttpMessage<List<UserAuthen>>> getUserList();
@GET("/user/info")
Call<HttpMessage<UserInfo>> getUserInfo();
}
- 调用API,获取数据
messageCall.enqueue(new Callback<HttpMessage<UserInfo>>() {
@Override
public void onResponse(Call<HttpMessage<UserInfo>> call, Response<HttpMessage<UserInfo>> response) {
Log.i(TAG, "onResponse: " + response.body().getCode());
}
@Override
public void onFailure(Call<HttpMessage<UserInfo>> call, Throwable t) {
Log.i(TAG, "onResponse: " + t.getMessage());
t.printStackTrace();
}
});
同理,data类型为泛型数组时:
Call<HttpMessage<List<UserAuthen>>> messageCall = userServiceAPI.getUserList();
messageCall.enqueue(new Callback<HttpMessage<List<UserAuthen>>>() {
@Override
public void onResponse(Call<HttpMessage<List<UserAuthen>>> call, Response<HttpMessage<List<UserAuthen>>> response) {
Log.i(TAG, "onResponse: " + response.body().getCode());
}
@Override
public void onFailure(Call<HttpMessage<List<UserAuthen>>> call, Throwable t) {
Log.i(TAG, "onResponse: " + t.getMessage());
t.printStackTrace();
}
});
如果返回正常数据,则可以正确解析并返回,否正直接抛出异常,怎么解决呢?
同样也需要自定义一个自己的转换器,需要三个类:
-
GsonConverFactory
- GsonResponseBodyConverter
- GsonRequestBodyConverter
直接从源码中复制出来 换成自己的名字即可,,现在只处理响应体转换器GsonResponseBodyConverter,代码如下:
- 在GsonConverFactory中返回自己的转换器,至展示关键部分
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
Log.w("TYPE", "类型是 " + type.getTypeName());//
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new WGsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new WGsonRequestBodyConverter<>(gson, adapter);
}
- 在WGsonResponseBodyConverter中做状态判断:
public T convert(ResponseBody value) throws IOException {
try {
//因为value只能被读取一次,所以这里必须把读取结果存起来,给下次使用
String reponseString = value.string();
HttpMessage httpMessage = gson.fromJson(reponseString, HttpMessage.class);
if (httpMessage.getCode() != 200) {
return (T) httpMessage;//直接返回,data字段不做类型转换
}
MediaType contentType = value.contentType();
Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8;
InputStream inputStream = new ByteArrayInputStream(reponseString.getBytes());
Reader reader = new InputStreamReader(inputStream, charset);
JsonReader jsonReader = gson.newJsonReader(reader);
return adapter.read(jsonReader);
} finally {
value.close();
}
}
使用自定义的转换器即可:
userServiceAPI = new Retrofit.Builder()
.client(builder.build())
.baseUrl(this.host).addConverterFactory(WGsonConverFactory.create())//使用自己的转换器
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(GsonTestAPI.class);