Используя Square Retrofit Client, можно ли отменить запрос на выполнение? Если да, то как?

Я использую Square Retrofit Client для выполнения коротких запросов json от приложения Android. Есть ли способ отменить запрос? Если да, то как?

Ответ 1

Для отмены запроса async 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 changelog выполняется .cancel(Object tag). Мы должны ожидать такую ​​же особенность в предстоящей Retrofit:

Вы можете использовать фактический объект Request для его отмены

okClient.cancel(request);

или если вы указали тег на Request.Builder, вы должны использовать

okClient.cancel(request.tag());

Все текущие, выполненные или ожидающие запросы помещаются в очередь внутри Dispatcher, okClient.getDispatcher(). Вы также можете вызвать метод отмены на этом объекте. Метод Cancel уведомит OkHttp Engine, чтобы убить соединение с хостом, если оно уже установлено.

Изменить 2. В Retrofit 2 есть полнофункциональные запросы на отмену.

Ответ 2

Оберните обратный вызов в объекте делегата, который реализует обратный вызов как Что ж. Вызовите какой-то метод, чтобы очистить делегата и просто его no-op, когда он получает ответ.

Посмотрите на следующее обсуждение

https://plus.google.com/107765816683139331166/posts/CBUQgzWzQjS

Лучшая стратегия будет отменять выполнение обратного вызова

fooobar.com/questions/812900/...

Ответ 3

Я реализовал отмененный класс обратного вызова на основе ответа fooobar.com/questions/812900/...

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);

Ответ 5

Это для модификации 2.0, метод call.cancel(), который отменяет вызов в полете. ниже это определение документа для него.

retrofit2.Call

public abstract void cancel()

Отмените этот вызов. Будет предпринята попытка отменить звонки в полете, и если вызов еще не был выполнен, он никогда не будет.

Ответ 6

Согласно Retrofit 2.0 beta 3 changelog по ссылке https://github.com/square/retrofit/releases/tag/parent-2.0.0-beta3

Новый метод: isCanceled() возвращает ли вызов отменен. Используйте это в onFailure, чтобы определить, был ли обратный вызов вызван с отменой или фактическим отказом транспорта.

Это должно облегчить работу.

Ответ 7

Возможно, я немного опоздал, но я нашел решение. Я не смог предотвратить выполнение запроса, но если вы удовлетворены выполняемым запросом и ничего не делаете, вы можете проверить этот вопрос и ответ, оба сделаны мной.