Как получить запрос, ответ и десериализованный объект как конверт из вызова Retrofit в Observer - PullRequest
0 голосов
/ 17 мая 2019

Я использую 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. Любая идея о том, как выполнить задачу, или любое более простое решение?

...