Q: 当我们的服务器的json数据形如下面:
{
code:0,//这里的数字代表了服务器返回的不同状况,通常只有1才是正确的
msg:"提示信息",//这里代表了返回数据的提示信息
data:<obj>|<array> //这里真正需要的数据
}
可是很多时候,我们队数据的处理是一样的,只有code==1的时候才能需要解析data的数据,其他时候我们直接抛异常处理.
那么我们怎么封装统一处理数据呢?
有两种方法:
1.使用Rxjava 的特性,在返回数据前,统一对数据进行解析处理;
2.使用Retrofit 的特性,在创建Retrofit,有一个方法Retrofit.Build#addConverterFactory(Converter.Factory factory),可以对服务器的数据进行解析.通常我们这样写:
new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create())
进行我们自定义一个自己的ConverterFactory
例如
定义一个接口
public class ApiResponse<T> {
int code;
String message;
T data;
public boolean isSuccess(){
return code == 1;
}
}
public interface HouseApi {
@POST("v1/user/login")
@FormUrlEncoded
Observable<ApiResponse> login();
}
使用Rxjava 的特性解决
//1.先得到Retrofit
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl(Constants.URLS.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build().create(HouseApi.class).login(loginCode, md5Password);
//2.然后使用map方法统一对数据进行出
.map(ApiResponseMapper.create())
//
public class ApiResponseMapper {
public static final String TAG = ApiResponseMapper.class.getSimpleName();
public static <T> Function<ApiResponse<T>, T> create() {
return apiResponse -> {
if (apiResponse.isSuccess()) {//就是判断code==1
return apiResponse.getData();
} else {//不然就会跑异常
throw new ApiException(apiResponse.getMsg());
}
};
}
}
//可是这样会出现一个问题,集合每个网络请求都调用:
Observable#map(ApiResponseMapper.create())
其实也是一个麻烦,没意义.
Q:有没有一个方法,完全根据我们自己服务器的数据的特性解决这个问题呢?
A:使用Retrofit 的特性:addConverterFactory(GsonConverterFactory.create())
GsonConverterFactory 其实就是一个对服务器的数据解析gson解析的方法, 我们可以对解析后的数据在进行判断code是否为1的处理,不符合就跑异常,岂不是非常好?
public class QxydGsonConverterFactory extends Converter.Factory{
..
}
改方法继承Converter.Factory ,复写responseBodyConverter和requestBodyConverter方法即可
- 前者是对response 的数据gson解析后判断code和类型;
- 后者是对requese sh
public class DsGsonConverterFactory extends Converter.Factory {
public static final String TAG = DsGsonConverterFactory.class.getSimpleName();
private final Gson gson;
private DsGsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
public static DsGsonConverterFactory create() {
return create(new Gson());
}
public static DsGsonConverterFactory create(Gson gson) {
return new DsGsonConverterFactory(gson);
}
@Nullable
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Nullable
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter(gson, adapter);
}
private final static class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
private final static class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
T entity = adapter.read(jsonReader);
if(entity instanceof ApiResponse){
ApiResponse result = (ApiResponse) entity;
if(!result.isSuccess()){
if(result.getMsg() != null){
Log.v(TAG, "convert: " + result.getMsg());
}
throw new ApiException(result.getMsg());
}
}
return entity;
}catch (Exception e){
e.printStackTrace();
throw e;
} finally {
value.close();
}
}
}
最后使用的使用,创建Retrofit使用addConverterFactory就行了
Retrofit retrofit = new Retrofit.Builder()
````
.addConverterFactory(DsGsonConverterFactory .create(gson))
```