web-dev-qa-db-fra.com

Retrofit "IllegalStateException: déjà exécuté"

J'ai un appel réseau Retrofit que j'aimerais exécuter toutes les 5 secondes. Mon code actuel:

Handler h = new Handler();
int delay = 5000; //milliseconds

h.postDelayed(new Runnable() {
    public void run() {
        call.enqueue(new Callback<ApiResponse>() {
            @Override
            public void onResponse(Response<ApiResponse> response) {
                Log.d("api", "response: " + response.body().getPosition().getLatitude().toString());
            }

            @Override
            public void onFailure(Throwable t) {

            }
        });
        h.postDelayed(this, delay);
    }
}, delay);

Cela s'exécute une fois, mais lance ensuite ce qui suit:

Java.lang.IllegalStateException: déjà exécuté. à retrofit2.OkHttpCall.enqueue (OkHttpCall.Java:52) à retrofit2.ExecutorCallAdapterFactory $ ExecutorCallbackCall.enqueue (ExecutorCallAdapterFactory.Java:57) à orbyt.project.MyFragagment $ 1.run (MyF:agment)

Quel est le problème ici?

En bonus: quelle est la meilleure façon de gérer cela? Je mettrai à jour une carte à chaque mise à jour. Je pensais à essayer d'utiliser Rx mais je ne sais pas si c'est un cas d'utilisation approprié, ou comment l'implémenter.

28
Orbit

Un Call ne peut être utilisé qu'une seule fois. Sa documentation vous indique comment l'utiliser plusieurs fois:

Utilisez clone() pour effectuer plusieurs appels avec les mêmes paramètres vers le même serveur Web; cela peut être utilisé pour implémenter l'interrogation ou pour réessayer un appel ayant échoué.

Utilisez donc call.clone().enqueue(..) for Asynchornous and call.clone().execute() for Synchornous respectivement pour vous assurer que vous disposez d'un Call frais et non exécuté pour chaque demande.

62
Jake Wharton