Есть ли у нас возможность прекратить запрос в OkHttp Interceptor?

В нашем приложении мы встретились с одним специальным случаем - если наш App.specialFlag == true, нам нужно остановить любой запрос из нашего кода. И мы думаем, что наилучшим подходом в этой ситуации является специальный Interceptor, который остановит любые наши запросы, примерно так:

if (App.specialFlag) {
    // Somehow stop request
} else {
    return chain.proceed(chain.request());
}

Кроме того, следует отметить, что мы используем RxJavaCallAdapterFactory для переноса ответов в Observable s.

Но мы не видим никаких методов для остановки запроса в OkHttp Interceptors.

Мы разработали два способа решения нашей проблемы:

a) Создайте специальный ApiService.class для упаковки каждого запроса в нашем API следующим образом:

public Observable<User> getUserDetails() {
    if (App.specialFlag) {
        return Observable.just(null);
    }
    return api.getUserDetails();
}

Но мы считаем, что это уродливое и громоздкое решение.

b) Бросьте a RuntimeException в Interceptor, а затем поймайте его в любом месте, где мы используем наш API.

Второе решение также не очень хорошо, потому что нам нужно включить в наши цепочки множество операторов onErrorResumeNext.

Может кто-нибудь знает, как справиться с нашей ситуацией более "умным" способом?..

Спасибо заранее!

Ответ 1

Один из способов предотвратить выполнение запроса (до его запуска) - просто выполнить, как вы пытались, но с добавлением Response.Builder:

if (App.specialFlag) {
    return new Response.Builder()
                       .code(600) //Simply put whatever value you want to designate to aborted request.
                       .protocol(Protocol.HTTP_2)
                       .message("Dummy response")
                       .request(chain.request())
                       .build();
} else {
    return chain.proceed(chain.request());
}

ОБНОВЛЕНИЕ 26/09/2019 Обновленный ответ с деталями, упомянутыми Bobstring

Ответ 2

Одна из недостатков в принятом ответе заключается в том, что вам нужно указать протокол и сообщение. Если вы не укажете, что получите Исключение. Выглядит так:

if (App.specialFlag) {
    return new Response.Builder()
                       .code(418) //Whatever code
                       .protocol(Protocol.HTTP_2)
                       .message("Dummy response")
                       .request(chain.request())
                       .build();
} else {
    return chain.proceed(chain.request());
}

Ответ 3

  • Я бы предложил поставить логику управления script за пределы OkHttp, так как она используется только для создания HTTP-запроса. Как инициировать запрос и как обрабатывать ответ для обновления пользовательского интерфейса, его не нужно заботиться,

  • Если вы хотите, вы можете создать класс, унаследованный от okhttp3.Interceptor, затем переопределить функцию перехвата и поместить свою логику управления script внутрь.

    OkHttpClient client = new OkHttpClient.Builder()
       .connectTimeout(20, TimeUnit.SECONDS)
       .readTimeout(20, TimeUnit.SECONDS)
       .addInterceptor(new Interceptor())
       .build();