前因:由于项目功能的增加,所需要接人的后台接口也不只一个,返回格式的差异化也不可避免。
思路:接口返回时我们所必须的值分别是Http status code、HTTP status message or null if unknown、和body。当我们在接收数据时先把数据转换为JsonObject,然后在CallAdapterFactory中转换为指定格式
new Retrofit.Builder()
.addConverterFactory(CustomGsonConverterFactory.create())
.addCallAdapterFactory(new LglLiveDataCallAdapterFactory())
.baseUrl(Constants.BASE_LGL_URL)
.client(okHttpClient)
.build()
.create(LGLApiService.class);
CustomGsonConverterFactory.java
public class CustomGsonConverterFactory extends Converter.Factory {
private final Gson gson;
private CustomGsonConverterFactory(Gson gson) {
if (gson == null) {
throw new NullPointerException("gson == null");
}
this.gson = gson;
}
public static CustomGsonConverterFactory create() {
return create(new Gson());
}
public static CustomGsonConverterFactory create(Gson gson) {
return new CustomGsonConverterFactory(gson);
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
TypeAdapter<?> adapter1 = gson.getAdapter(TypeToken.get(JsonObject.class));
return new CustomGsonResponseBodyConverter<>(gson, adapter1);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new CustomGsonRequestBodyConverter<>(gson, adapter);
}
}
CustomGsonRequestBodyConverter.java
public class CustomGsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
public 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;
CustomGsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public RequestBody convert(T value) {
return RequestBody.create(MEDIA_TYPE, value.toString());
}
}
CustomGsonResponseBodyConverter.java
public class CustomGsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private static final String TAG = "CustomGsonResponseBodyC";
private final Gson gson;
private final TypeAdapter<T> adapter;
CustomGsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public T convert(ResponseBody value) throws IOException {
byte[] bytes = value.bytes();
String jsonString = new String(bytes);
Reader reader = StringToReader(jsonString);
JsonReader jsonReader = gson.newJsonReader(reader);
try {
return adapter.read(jsonReader);
} finally {
reader.close();
jsonReader.close();
}
}
/**
* String转Reader
*
* @param json
* @return
*/
private Reader StringToReader(String json) {
Reader reader = new StringReader(json);
return reader;
}
}
LglLiveDataCallAdapterFactory.java
public class LglLiveDataCallAdapterFactory extends CallAdapter.Factory {
@Override
public CallAdapter<?, ?> get(@NonNull Type returnType, @NonNull Annotation[] annotations, @NonNull Retrofit retrofit) {
if(!(returnType instanceof ParameterizedType)){
throw new IllegalArgumentException("返回值需为参数化类型");
}
if (getRawType(returnType) != LiveData.class) {
return null;
}
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Type custObservableType = getParameterUpperBound(0,(ParameterizedType)observableType);
return new LglLiveDataCallAdapter<>(custObservableType);
}
}
LglLiveDataCallAdapter.java
public class LglLiveDataCallAdapter<R> implements CallAdapter<R, LiveData<LglApiResult<R>>> {
public static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private final Type responseType;
public LglLiveDataCallAdapter(Type responseType) {
this.responseType = responseType;
}
@Override
public Type responseType() {
return responseType;
}
@Override
public LiveData<LglApiResult<R>> adapt(Call<R> call) {
AtomicBoolean started = new AtomicBoolean(false);
return new LiveData<LglApiResult<R>>() {
@Override
protected void onActive() {
super.onActive();
if (started.compareAndSet(false, true)) {
call.enqueue(new Callback<R>() {
@Override
public void onResponse(Call<R> call, Response<R> response) {
LglApiResult apiResult = new LglApiResult<>();
apiResult.code = response.code();
apiResult.msg = response.message();
apiResult.data = null;
if (response.isSuccessful()) {
ResponseBody responseBody = ResponseBody.create(MEDIA_TYPE, response.body().toString());
Gson gson = new Gson();
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(responseType));
CustomGsonResponseBodyConverter<?> converter = new CustomGsonResponseBodyConverter<>(gson, adapter);
try {
apiResult.data = converter.convert(responseBody);
} catch (IOException e) {
e.printStackTrace();
}
}
postValue(apiResult);
}
@Override
public void onFailure(Call<R> call, Throwable t) {
LglApiResult<R> apiResult = new LglApiResult<>();
apiResult.code = 999;
apiResult.msg = t.getMessage();
apiResult.data = null;
postValue(apiResult);
}
});
}
}
};
}
}