Java 使用 Square 的 Retrofit Client,是否可以取消正在进行的请求?如果是这样怎么办?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18131382/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Square's Retrofit Client, is it possible to cancel an in progress request? If so how?
提问by Alfie Hanssen
I'm using Square's Retrofit Client to make short-lived json requests from an Android App. Is there a way to cancel a request? If so, how?
我正在使用 Square 的 Retrofit Client 从 Android 应用程序发出短暂的 json 请求。有没有办法取消请求?如果是这样,如何?
回答by diesel
Wrap the callback in a delegate object that implements Callback as well. Call some method to clear out the delegate and have it just no-op whenever it gets a response.
将回调包装在实现回调的委托对象中。调用一些方法来清除委托,并在收到响应时让它无操作。
Look at the following discussion
看下面的讨论
https://plus.google.com/107765816683139331166/posts/CBUQgzWzQjS
https://plus.google.com/107765816683139331166/posts/CBUQgzWzQjS
Better strategy would be canceling the callback execution
更好的策略是取消回调执行
回答by Nikola Despotoski
For canceling async Retrofitrequest, you can achieve it by shutting down the ExecutorServicethat performs the async request.
对于取消异步Retrofit请求,您可以通过关闭执行异步请求的ExecutorService来实现。
For example I had this code to build the RestAdapter
:
例如,我有这个代码来构建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()));
and had this method for forcefully abandoning the requests:
并有这种强行放弃请求的方法:
public void stopAll(){
List<Runnable> pendingAndOngoing = mExecutorService.shutdownNow();
// probably await for termination.
}
Alternatively you could make use of ExecutorCompletionService
and either poll(timeout, TimeUnit.MILISECONDS)
or take()
all ongoing tasks. This will prevent thread pool not being shut down, as it would do with shutdownNow()
and so you could reuse your ExecutorService
或者,您可以使用ExecutorCompletionService
和poll(timeout, TimeUnit.MILISECONDS)
或take()
所有正在进行的任务。这将防止线程池不被关闭,因为它会这样做,shutdownNow()
因此您可以重用您的ExecutorService
Hope it would be of help for someone.
希望它对某人有帮助。
Edit: As of OkHttp 2 RC1changelogperforming a .cancel(Object tag)
is possible. We should expect the same feature in upcoming Retrofit:
编辑:从 OkHttp 2 RC1更改日志开始,执行 a.cancel(Object tag)
是可能的。我们应该期待即将到来的 Retrofit 中的相同功能:
You can use actual Request
object to cancel it
您可以使用实际Request
对象取消它
okClient.cancel(request);
okClient.cancel(request);
or if you have supplied tag to Request.Builder
you have to use
或者如果您提供了标签,Request.Builder
则必须使用
okClient.cancel(request.tag());
okClient.cancel(request.tag());
All ongoing, executed or pending requests are queued inside Dispatcher
, okClient.getDispatcher()
. You can call cancel method on this object too. Cancel method will notify OkHttp Engine
to kill the connection to the host, if already established.
所有正在进行的、已执行的或未决的请求都在Dispatcher
,中排队okClient.getDispatcher()
。您也可以在此对象上调用取消方法。Engine
如果已经建立,Cancel 方法将通知 OkHttp 终止与主机的连接。
Edit 2: Retrofit 2 has fully featured canceling requests.
编辑 2:改造 2 具有全功能取消请求。
回答by Vektor88
I might be a bit late, but I've possibly found a solution. I haven't been able to prevent a request from being executed, but if you're satisfied with the request being performed and not doing anything, you might check thisquestion and answer, both made by me.
我可能有点晚了,但我可能已经找到了解决方案。我无法阻止请求被执行,但是如果您对正在执行的请求感到满意并且没有做任何事情,您可以检查这个问题和答案,两者都是由我提出的。
回答by Biggemot
I've implemented cancelable callback class based on answer https://stackoverflow.com/a/23271559/5227676
我已经根据答案实现了可取消的回调类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);
}
Usage example
使用示例
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);
回答by cgr
Now there is an easy way in latest version of Retrofit V 2.0.0.beta2. Can implement retry too.
Take a look here How to cancel ongoing request in retrofit when retrofit.client.UrlConnectionClient is used as client?
现在在最新版本的 Retrofit V 2.0.0.beta2 中有一个简单的方法。也可以实现重试。
看看这里当retrofit.client.UrlConnectionClient用作客户端时如何取消改造中正在进行的请求?
回答by CarlosRivin
According to the Retrofit 2.0 beta 3 changelog via link https://github.com/square/retrofit/releases/tag/parent-2.0.0-beta3
根据通过链接https://github.com/square/retrofit/releases/tag/parent-2.0.0-beta3的 Retrofit 2.0 beta 3 变更日志
New: isCanceled() method returns whether a Call has been canceled. Use this in onFailure to determine whether the callback was invoked from cancelation or actual transport failure.
新:isCanceled() 方法返回调用是否已被取消。在 onFailure 中使用它来确定回调是从取消还是实际传输失败中调用的。
This should make stuff easier.
这应该会让事情变得更容易。
回答by AAnkit
This is for retrofit 2.0, the method call.cancel()is there which cancels the in-flight call as well. below is the document definition for it.
这是用于改造 2.0 的,方法call.cancel()也可以取消飞行中的调用。下面是它的文档定义。
retrofit2.Call
public abstract void cancel()
Cancel this call. An attempt will be made to cancel in-flight calls, and if the call has not yet been executed it never will be.
取消这个电话。将尝试取消正在进行的调用,如果调用尚未执行,则永远不会执行。