我正在使用Square的Retrofit Client从Android应用程序发出短暂的json请求。有办法取消请求吗?如果是这样,怎么样?
答案 0 :(得分: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 changelog开始执行.cancel(Object tag)
是可能的。我们应该期待即将推出的Retrofit中的相同功能:
您可以使用实际Request
对象取消
okClient.cancel(request);
或者如果您向Request.Builder
提供了标签,则必须使用
okClient.cancel(request.tag());
所有正在进行,已执行或待处理的请求都在Dispatcher
,okClient.getDispatcher()
内排队。您也可以在此对象上调用cancel方法。如果已经建立,取消方法将通知OkHttp Engine
以终止与主机的连接。
编辑2 :Retrofit 2具有全功能的取消请求。
答案 1 :(得分:3)
将回调包装在实现Callback的委托对象中 好。调用一些方法来清除委托并完成它 无论什么时候得到回应都会没有。
请看以下讨论
https://plus.google.com/107765816683139331166/posts/CBUQgzWzQjS
更好的策略是取消回调执行
答案 2 :(得分: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);
答案 3 :(得分:2)
现在最新版本的Retrofit V 2.0.0.beta2有一个简单的方法。也可以实施重试 看看How to cancel ongoing request in retrofit when retrofit.client.UrlConnectionClient is used as client?
答案 4 :(得分:2)
这是为了改造2.0,方法 call.cancel()也可以取消正在进行的通话。下面是它的文档定义。
retrofit2.Call
public abstract void cancel()
取消此通话。将尝试取消正在进行的呼叫,如果呼叫尚未执行,则永远不会执行。
答案 5 :(得分:1)
根据Retrofit 2.0 beta 3更改日志,通过链接https://github.com/square/retrofit/releases/tag/parent-2.0.0-beta3
新增:isCanceled()方法返回是否已取消呼叫。在onFailure中使用它来确定是否从取消或实际传输失败中调用了回调。
这应该会让事情变得更容易。
答案 6 :(得分:0)
我可能有点晚了,但我可能找到了解决方案。 我无法阻止请求被执行,但如果您对正在执行的请求感到满意而没有做任何事情,您可以查看我this的问题和回答