Я использую Retrofit с Java Rx для приложения для Android. Мне было предложено получить в SingleObserver объект, подобный этому:
class Envelope<T> {
public Request request;
public Response response;
public T data;
}
, где Запрос и Ответ - это необработанные okhttp3.Request и okhttp3.Response и T мой десериализованный тип данных java из Json.
Я нашел несколько ресурсов в сети, отбрасывая некоторые данные из фактического ответа (например, здесь ), но ни один из них не пытался расширить возвращаемый объект.
Я попробовал также несколько подходов с использованием пользовательских Конвертеров и CallAdapters ( пример ), но безуспешно.
Это то, что я придумал.
Это мой модифицированный экземпляр:
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(new EnvelopeConverterFactory())
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(CustomCallAdapterFactory.create())
.client(client)
.build();
Это мой КонвертерКонвертерный Завод:
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
Type envelopeType = ((ParameterizedType) type).getActualTypeArguments()[0];
Converter<ResponseBody, ?> delegate =
retrofit.nextResponseBodyConverter(this, envelopeType, annotations);
return new EnvelopeConverter(delegate);
}
Это мой конверт конверта:
public BaseApiService.Envelope<T> convert(ResponseBody responseBody) throws IOException {
T data = delegate.convert(responseBody);
BaseApiService.Envelope<T> envelope = new BaseApiService.Envelope<>();
envelope.data = data;
return envelope;
}
Мой CustomCallAdapter:
[...]
private final RxJava2CallAdapterFactory original;
[...]
public CallAdapter<?, ?> get(@NonNull Type returnType,
@NonNull Annotation[] annotations,
@NonNull Retrofit retrofit) {
return new RxCallAdapterWrapper(retrofit, original.get(returnType, annotations, retrofit));
}
private static class RxCallAdapterWrapper<R> implements CallAdapter<R, Single<BaseApiService.Envelope<R>>> {
private final CallAdapter<R, Single<BaseApiService.Envelope<R>>> wrapped;
[...]
public Single<BaseApiService.Envelope<R>> adapt(@NonNull Call<R> call) {
Single<BaseApiService.Envelope<R>> result = wrapped.adapt(call);
final Request request = call.request();
return result.map(new Function<BaseApiService.Envelope<R>, BaseApiService.Envelope<R>>() {
@Override
public BaseApiService.Envelope<R> apply(BaseApiService.Envelope<R> rEnvelope) {
rEnvelope.request = request;
return rEnvelope;
}
}).onErrorResumeNext(new Function<Throwable, SingleSource<BaseApiService.Envelope<R>>>() {
@Override
public SingleSource<BaseApiService.Envelope<R>> apply(@NonNull Throwable throwable) {
return Single.error(throwable);
}
});
}
}
Наблюдатель:
mApiService.requestRepo(repo)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableSingleObserver<BaseApiService.Envelope<ResponseRepos>>() {
@Override
public void onSuccess(BaseApiService.Envelope<ResponseRepos> responseReposEnvelope) {
// Do something with responseReposEnvelope.data,
// responseReposEnvelope.request and responseReposEnvelope.response
}
В настоящее время я не могу установить Response в объект Envelope. Любая идея о том, как выполнить задачу, или любое более простое решение?