Using Square's Retrofit Client, Is It Possible To Cancel An In Progress Request? If So How?
Solution 1:
For canceling async Retrofit request, you can achieve it by shutting down the ExecutorService that performs the async request.
For example I had this code to build the RestAdapter
:
BuilderrestAdapter=newRestAdapter.Builder();
restAdapter.setEndpoint(BASE_URL);
restAdapter.setClient(okClient);
restAdapter.setErrorHandler(mErrorHandler);
mExecutorService = Executors.newCachedThreadPool();
restAdapter.setExecutors(mExecutor, newMainThreadExecutor());
restAdapter.setConverter(newGsonConverter(gb.create()));
and had this method for forcefully abandoning the requests:
publicvoidstopAll(){
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
Hope it would be of help for someone.
Edit: As of OkHttp 2 RC1changelog performing a .cancel(Object tag)
is possible. We should expect the same feature in upcoming Retrofit:
You can use actual Request
object to cancel it
okClient.cancel(request);
or if you have supplied tag to Request.Builder
you have to use
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.
Edit 2: Retrofit 2 has fully featured canceling requests.
Solution 2:
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
Better strategy would be canceling the callback execution
Solution 3:
I've implemented cancelable callback class based on answer https://stackoverflow.com/a/23271559/5227676
publicabstractclassCancelableCallback<T> implementsCallback<T> {
privatestatic List<CancelableCallback> mList = new ArrayList<>();
private boolean isCanceled = false;
private Object mTag = null;
publicstaticvoidcancelAll() {
Iterator<CancelableCallback> iterator = mList.iterator();
while (iterator.hasNext()){
iterator.next().isCanceled = true;
iterator.remove();
}
}
publicstaticvoidcancel(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();
}
}
}
}
publicCancelableCallback() {
mList.add(this);
}
publicCancelableCallback(Object tag) {
mTag = tag;
mList.add(this);
}
publicvoidcancel() {
isCanceled = true;
mList.remove(this);
}
@Override
public final voidsuccess(T t, Response response) {
if (!isCanceled)
onSuccess(t, response);
mList.remove(this);
}
@Override
public final voidfailure(RetrofitError error) {
if (!isCanceled)
onFailure(error);
mList.remove(this);
}
publicabstractvoidonSuccess(T t, Response response);
publicabstractvoidonFailure(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 allCancelableCallback.cancelAll();
// or cancel by tagCancelableCallback.cancel(TAG);
Solution 4:
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.
retrofit2.Call
publicabstractvoidcancel()
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.
Solution 5:
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?
Post a Comment for "Using Square's Retrofit Client, Is It Possible To Cancel An In Progress Request? If So How?"