使用Square的改造客户端,是否可以取消正在进行的请求?如果是这样,怎么办?



我正在使用Square的改装客户端从Android应用程序发出短暂的json请求。有没有办法取消请求?如果是,如何?

要取消异步改装请求,可以通过关闭执行异步请求的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.
}

或者,您可以使用ExecutorCompletionServicepoll(timeout, TimeUnit.MILISECONDS)take()所有正在进行的任务。这将防止线程池不被关闭,就像它对shutdownNow()所做的那样,因此您可以重用ExecutorService

希望这对某人有帮助。

编辑:从OkHttp 2 RC1变更日志开始,可以执行.cancel(Object tag)。我们应该期待在即将到来的改装中有同样的功能:

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

okClient.cancel(request);

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

okClient.cancel(request.tag());

所有正在进行、执行或挂起的请求都在DispatcherokClient.getDispatcher()内排队。您也可以对此对象调用cancel方法。Cancel方法将通知OkHttp Engine终止与主机的连接(如果已经建立)。

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

将回调封装在实现回调的委托对象中好调用一些方法来清除委托,并使其无论何时得到回应,都不采取行动。

看看下面的讨论

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

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

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

根据通过链接进行的改装2.0测试版3更改日志https://github.com/square/retrofit/releases/tag/parent-2.0.0-beta3

New:isCanceled()方法返回Call是否已被取消。在onFailure中使用此选项可确定回调是从取消调用还是从实际传输失败调用。

这应该会让事情变得更容易。

我可能有点晚了,但我可能已经找到了解决方案。我无法阻止请求被执行,但如果你对正在执行的请求感到满意,并且什么都没做,你可以检查这个问题和答案,这两个问题都是我做的。

相关内容

最新更新