Vraag Met behulp van Square's Retrofit Client, is het mogelijk om een ​​lopende aanvraag te annuleren? Zo ja, hoe?


Ik gebruik de Retrofit Client van Square om kortstondige json-verzoeken uit een Android-app te maken. Is er een manier om een ​​aanvraag te annuleren? Zo ja, hoe?


18
2017-08-08 16:36


oorsprong


antwoorden:


Voor het annuleren van async retrofit verzoek, kunt u dit bereiken door het afsluiten van de ExecutorService die het asynchrone verzoek uitvoert.

Ik had bijvoorbeeld deze code om het te bouwen 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()));

en had deze methode om de verzoeken met geweld af te schaffen:

public void stopAll(){
   List<Runnable> pendingAndOngoing = mExecutorService.shutdownNow();
   // probably await for termination.
}

Als alternatief kunt u gebruik maken van ExecutorCompletionService en ook poll(timeout, TimeUnit.MILISECONDS) of take() alle lopende taken. Dit voorkomt dat threadpool wordt uitgeschakeld, zoals het zou doen met shutdownNow() en dus zou je je kunnen hergebruiken ExecutorService

Ik hoop dat het iemand kan helpen.

Bewerk: Vanaf OkHttp 2 RC1  changelog uitvoeren van een .cancel(Object tag) is mogelijk. We zouden dezelfde functie moeten verwachten in de komende Retrofit:

U kunt feitelijk gebruiken Request object om het te annuleren

okClient.cancel(request);

of als je een tag hebt opgegeven Request.Builder je moet gebruiken

okClient.cancel(request.tag());

Alle lopende, uitgevoerde of uitstaande aanvragen worden in de wachtrij geplaatst Dispatcher, okClient.getDispatcher(). U kunt ook de annuleringsmethode voor dit object aanroepen. Annuleer methode zal OkHttp op de hoogte brengen Engine om de verbinding met de host te verbreken, als deze al is ingesteld.

Bewerk 2: Retrofit 2 heeft volledige annuleringverzoeken.


22
2018-02-26 20:58



Wikkel de callback in een delegatieobject in dat Callback als implementeert   goed. Noem een ​​methode om de gedelegeerde vrij te maken en het recht te houden   no-op wanneer het een reactie krijgt.

Kijk naar de volgende discussie

https://plus.google.com/107765816683139331166/posts/CBUQgzWzQjS

Betere strategie zou het annuleren van de callback-uitvoering zijn

https://stackoverflow.com/a/23271559/1446469


3
2017-10-09 09:15



Ik heb annuleerbare callbackklasse geïmplementeerd op basis van antwoord 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);
}

Gebruik voorbeeld

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
2017-08-14 15:00



Nu is er een eenvoudige manier in de nieuwste versie van Retrofit V 2.0.0.beta2. Kan het opnieuw proberen ook uitvoeren.
Kijk hier eens Hoe een doorgaand verzoek bij retrofit te annuleren wanneer retrofit.client.UrlConnectionClient als client wordt gebruikt?


2
2017-10-01 12:10



Dit is voor retrofit 2.0, de methode call.cancel () is er die ook de oproep tijdens de vlucht annuleert. hieronder staat de documentdefinitie ervoor.

retrofit2.Call

public abstract void cancel()

Annuleer deze oproep. Er zal een poging worden gedaan om tijdens de vlucht gesprekken te annuleren en als de oproep nog niet is uitgevoerd, zal dit nooit gebeuren.


2
2018-03-10 06:34



Volgens de Retrofit 2.0 beta 3 changelog via link https://github.com/square/retrofit/releases/tag/parent-2.0.0-beta3

Nieuw: de methode isCanceled () retourneert of een oproep is geannuleerd. Gebruik dit in onFailure om te bepalen of de callback werd opgeroepen door annulering of daadwerkelijke transportfout.

Dit zou dingen eenvoudiger moeten maken.


1
2018-01-11 13:08



Ik ben misschien wat laat, maar ik heb mogelijk een oplossing gevonden. Ik heb niet kunnen voorkomen dat een verzoek wordt uitgevoerd, maar als u tevreden bent met het verzoek dat wordt uitgevoerd en niets doet, kunt u controleren deze vraag en antwoord, beide gemaakt door mij.


0
2018-04-24 18:24