Я использую клиент Square Retrofit для выполнения кратковременных запросов json из приложения Android. Есть ли способ отменить запрос? Если да, то как?
Можно ли отменить текущий запрос с помощью клиента Square Retrofit? Если да, то как?
Ответы (7)
Чтобы отменить асинхронный запрос Retrofit, вы можете отключить ExecutorService, который выполняет асинхронный запрос.
Например, у меня был этот код для сборки RestAdapter
:
Builder restAdapter = new RestAdapter.Builder();
restAdapter.setEndpoint(BASE_URL);
restAdapter.setClient(okClient);
restAdapter.setErrorHandler(mErrorHandler);
mExecutorService = Executors.newCachedThreadPool();
restAdapter.setExecutors(mExecutor, new MainThreadExecutor());
restAdapter.setConverter(new GsonConverter(gb.create()));
и имел этот метод для принудительного отказа от запросов:
public void stopAll(){
List<Runnable> pendingAndOngoing = mExecutorService.shutdownNow();
// probably await for termination.
}
В качестве альтернативы вы можете использовать ExecutorCompletionService
и либо poll(timeout, TimeUnit.MILISECONDS)
, либо take()
все текущие задачи. Это предотвратит закрытие пула потоков, как это было бы с shutdownNow()
, и поэтому вы можете повторно использовать свой ExecutorService
Надеюсь, кому-то это поможет.
Изменить: начиная с OkHttp 2 RC1 журнал изменений возможно выполнение .cancel(Object tag)
. Мы должны ожидать ту же функцию в предстоящей модернизации:
Вы можете использовать фактический объект Request
, чтобы отменить его.
okClient.cancel(request);
или если вы предоставили тег Request.Builder
, вы должны использовать
okClient.cancel(request.tag());
Все текущие, выполненные или ожидающие запросы помещаются в очередь внутри Dispatcher
, okClient.getDispatcher()
. Вы также можете вызвать метод отмены для этого объекта. Метод Cancel уведомит OkHttp Engine
о разрыве соединения с хостом, если оно уже установлено.
Редактировать 2. Дооснащение 2 имеет полнофункциональные запросы на отмену.
shutdownNode
? Потому что в настоящее время я выполняю это в потоке пользовательского интерфейса, и запрос/передача вообще не отменяется.
- person Konrad Reiche; 13.08.2014
Оберните обратный вызов в объект делегата, который также реализует обратный вызов. Вызовите какой-нибудь метод, чтобы очистить делегата и заставить его просто не работать всякий раз, когда он получает ответ.
Посмотрите на следующее обсуждение
https://plus.google.com/107765816683139331166/posts/CBUQgzWzQjS
Лучшей стратегией будет отмена выполнения обратного вызова
https://stackoverflow.com/a/23271559/1446469
Я реализовал отменяемый класс обратного вызова на основе ответа https://stackoverflow.com/a/23271559/5227676
public abstract class CancelableCallback<T> implements Callback<T> {
private static List<CancelableCallback> mList = new ArrayList<>();
private boolean isCanceled = false;
private Object mTag = null;
public static void cancelAll() {
Iterator<CancelableCallback> iterator = mList.iterator();
while (iterator.hasNext()){
iterator.next().isCanceled = true;
iterator.remove();
}
}
public static void cancel(Object tag) {
if (tag != null) {
Iterator<CancelableCallback> iterator = mList.iterator();
CancelableCallback item;
while (iterator.hasNext()) {
item = iterator.next();
if (tag.equals(item.mTag)) {
item.isCanceled = true;
iterator.remove();
}
}
}
}
public CancelableCallback() {
mList.add(this);
}
public CancelableCallback(Object tag) {
mTag = tag;
mList.add(this);
}
public void cancel() {
isCanceled = true;
mList.remove(this);
}
@Override
public final void success(T t, Response response) {
if (!isCanceled)
onSuccess(t, response);
mList.remove(this);
}
@Override
public final void failure(RetrofitError error) {
if (!isCanceled)
onFailure(error);
mList.remove(this);
}
public abstract void onSuccess(T t, Response response);
public abstract void onFailure(RetrofitError error);
}
Пример использования
rest.request(..., new CancelableCallback<MyResponse>(TAG) {
@Override
public void onSuccess(MyResponse myResponse, Response response) {
...
}
@Override
public void onFailure(RetrofitError error) {
...
}
});
// if u need to cancel all
CancelableCallback.cancelAll();
// or cancel by tag
CancelableCallback.cancel(TAG);
Это для модификации 2.0, есть метод call.cancel(), который также отменяет вызов в полете. ниже приведено определение документа для него.
retrofit2.Call
public abstract void cancel()
Отменить вызов. Будет предпринята попытка отменить текущие вызовы, и если вызов еще не был выполнен, он никогда не будет выполнен.
Теперь есть простой способ в последней версии Retrofit V 2.0.0.beta2. Также можно реализовать повторную попытку.
Посмотрите здесь Как отменить текущий запрос в модификации, когда в качестве клиента используется retrofit.client.UrlConnectionClient?
Согласно журналу изменений Retrofit 2.0 beta 3 по ссылке https://github.com/square/retrofit/releases/tag/parent-2.0.0-beta3
Новое: метод isCanceled() возвращает, был ли вызов отменен. Используйте это в onFailure, чтобы определить, был ли обратный вызов вызван отменой или фактическим сбоем транспорта.
Это должно облегчить задачу.
Я могу немного опоздать, но я, возможно, нашел решение. Мне не удалось предотвратить выполнение запроса, но если вы удовлетворены выполнением запроса и ничего не делаете, вы можете проверить этот вопрос и ответ, оба сделаны мной.