SquareのRetrofitクライアントを使用して、Android Appからjsonリクエストを短期間有効にします。リクエストをキャンセルする方法はありますか?ある場合、その方法は?
非同期Retrofitリクエストをキャンセルする場合は、非同期リクエストを実行する 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
を再利用できます。
それが誰かのために役立つことを願っています。
Edit:OkHttp 2以降 RC1changelog.cancel(Object tag)
を実行すると可能。今後のレトロフィットでも同じ機能が期待できます。
実際のRequest
オブジェクトを使用してキャンセルできます
okClient.cancel(request);
または、_Request.Builder
_にタグを指定した場合は、
okClient.cancel(request.tag());
進行中、実行済み、または保留中のすべてのリクエストは、Dispatcher
、okClient.getDispatcher()
内でキューに入れられます。このオブジェクトでキャンセルメソッドを呼び出すこともできます。 Cancelメソッドは、すでに確立されている場合、ホストへの接続を強制終了するようOkHttp Engine
に通知します。
編集2:Retrofit 2には、キャンセルのリクエストが完全に機能しています。
回答に基づいてキャンセル可能なコールバッククラスを実装しました 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);
コールバックを実装するデリゲートオブジェクトでコールバックもラップします。いくつかのメソッドを呼び出してデリゲートをクリアし、応答を受け取ったときに常に何もしないようにします。
次の議論を見てください
https://plus.google.com/107765816683139331166/posts/CBUQgzWzQjS
より良い戦略は、コールバックの実行をキャンセルすることです
これはレトロフィット2.0の場合で、メソッドcall.cancel()があり、実行中の呼び出しもキャンセルされます。以下はそのドキュメント定義です。
retrofit2.Call
public abstract void cancel()
この通話をキャンセルします。処理中の呼び出しをキャンセルする試みが行われ、呼び出しがまだ実行されていない場合は行われません。
最新バージョンのRetrofit V 2.0.0.beta2には簡単な方法があります。再試行も実装できます。
ここを見てください retrofit.client.UrlConnectionClientがクライアントとして使用されている場合に、レトロフィットで進行中のリクエストをキャンセルする方法
リンク経由のRetrofit 2.0ベータ3の変更ログによると https://github.com/square/retrofit/releases/tag/parent-2.0.0-beta
New:isCanceled()メソッドは、呼び出しがキャンセルされたかどうかを返します。これをonFailureで使用して、コールバックがキャンセルから呼び出されたか、実際のトランスポート障害から呼び出されたかを判別します。
これは物事を簡単にする必要があります。
少し遅れるかもしれませんが、解決策を見つけた可能性があります。リクエストが実行されるのを防ぐことはできませんでしたが、実行されたリクエストに満足し、何もしない場合は、私が作成した this の質問と回答を確認してください。