18

我正在使用 Square 的 Retrofit Client 从 Android 应用程序发出短暂的 json 请求。有没有办法取消请求?如果是这样,怎么做?

4

7 回答 7

22

取消异步改造请求,可以通过关闭执行异步请求的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 更改日志执行 a.cancel(Object tag)是可能的。我们应该期待即将到来的改造中具有相同的功能:

您可以使用实际Request对象取消它

okClient.cancel(request);

或者如果您提供了标签,Request.Builder则必须使用

okClient.cancel(request.tag());

所有正在进行的、已执行的或待处理的请求都在Dispatcher,中排队okClient.getDispatcher()。您也可以在此对象上调用取消方法。Cancel 方法将通知 OkHttp 终止Engine与主机的连接(如果已建立)。

编辑 2:改造 2 具有功能齐全的取消请求。

于 2014-02-26T20:58:32.620 回答
3

将回调包装在一个也实现回调的委托对象中。调用一些方法来清除委托,并让它在收到响应时停止操作。

看下面的讨论

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

更好的策略是取消回调执行

https://stackoverflow.com/a/23271559/1446469

于 2013-10-09T09:15:25.337 回答
3

我已经根据答案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);
于 2015-08-14T15:00:37.290 回答
2

这是针对改造 2.0 的,方法call.cancel()也可以取消飞行中的调用。下面是它的文档定义。

retrofit2.Call

public abstract void cancel()

取消此通话。将尝试取消进行中的呼叫,如果呼叫尚未执行,则永远不会执行。

于 2016-03-10T06:34:29.287 回答
1

现在在 Retrofit V 2.0.0.beta2 的最新版本中有一个简单的方法。也可以实现重试。
看看这里当retrofit.client.UrlConnectionClient 用作客户端时,如何在改造中取消正在进行的请求?

于 2015-10-01T12:10:53.263 回答
1

根据通过链接https://github.com/square/retrofit/releases/tag/parent-2.0.0-beta3的改造 2.0 beta 3 更新日志

新增内容:isCanceled() 方法返回调用是否已被取消。在 onFailure 中使用它来确定回调是从取消还是实际传输失败中调用的。

这应该使事情变得更容易。

于 2016-01-11T13:08:38.090 回答
0

我可能有点晚了,但我可能已经找到了解决方案。我无法阻止请求被执行,但是如果您对正在执行的请求感到满意并且没有做任何事情,您可以查看这个问题和答案,两者都是由我提出的。

于 2014-04-24T18:24:16.020 回答