我使用 LiveData 调用适配器进行改造,改编自 google 示例
public interface ApiService {
@GET("?schema=1.2&form=cjson&byCategories=liveChannels&range=1-500&count=true")
LiveData<ApiResponse<Page<Media>>> getChannels();
}
我必须使用不同的端点,所以我想让 ApiResponse 通用。ApiResponse 将是接口或抽象的,并且对于所有这些端点都有不同的变体;我不想为每个扩展 ApiResponse 的类编写不同的 LiveData 扩展。
我想做类似的事情:
RetrofitLiveData<R, E extends ApiResponse<R>> extends LiveData<E<R>>
(我知道前面的代码是不可编译的,它只是我想要的一个例子)
然后在改造界面中我可以:
LiveData<Endpoint1ApiResponse<Endpoint1Data>>
LiveData<Endpoint2ApiResponse<Endpoint2Data>>
LiveData<Endpoint3ApiResponse<Endpoint3Data>>
public class LiveDataCallAdapterFactory extends CallAdapter.Factory {
@Override
public CallAdapter<?, ?> get(@NonNull Type returnType, @NonNull Annotation[] annotations,
@NonNull Retrofit retrofit) {
if (getRawType(returnType) != LiveData.class) {
return null;
}
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class<?> rawObservableType = getRawType(observableType);
if (rawObservableType != ApiResponse.class) {
throw new IllegalArgumentException("type must be a resource");
}
if (! (observableType instanceof ParameterizedType)) {
throw new IllegalArgumentException("resource must be parameterized");
}
Type bodyType = getParameterUpperBound(0, (ParameterizedType) observableType);
return new LiveDataCallAdapter<>(bodyType);
}
}
public class LiveDataCallAdapter<R> implements CallAdapter<R, LiveData<ApiResponse<R>>> {
private final Type responseType;
public LiveDataCallAdapter(Type responseType) {
this.responseType = responseType;
}
@Override
public Type responseType() {
return responseType;
}
@Override
public LiveData<ApiResponse<R>> adapt(@NonNull Call<R> call) {
return new RetrofitLiveData<R>(call);
}
}
public class RetrofitLiveData<R> extends LiveData<ApiResponse<R>> {
private final Call<R> call;
public RetrofitLiveData(Call<R> call) {
this.call = call;
}
@Override
protected void onActive() {
if (!call.isCanceled() && !call.isExecuted()) {
call.enqueue(callback);
}
}
private final Callback<R> callback = new Callback<R>() {
@Override
public void onResponse(@NonNull Call<R> call, @NonNull Response<R> response) {
postValue(new ApiResponse<>(response));
}
@Override
public void onFailure(@NonNull Call<R> call, @NonNull Throwable t) {
postValue(new ApiResponse<>(t));
}
};
public void cancel() {
if (!call.isCanceled()) {
call.cancel();
}
}
}
public class ApiResponse<T> {
public final int code;
@Nullable
public final T body;
@Nullable
public final String errorMessage;
public ApiResponse(Throwable error) {
code = 500;
body = null;
errorMessage = error.getMessage();
}
public ApiResponse(Response<T> response) {
// .......... not important here
}
public boolean isSuccessful() {
return code >= 200 && code < 300;
}
}