2016-05-03 5 views
1

Ich folgte diesem Link How to debounce a retrofit reactive request in java?, um eine nachträgliche reaktive Anfrage zu debuntieren. Unten ist mein Stück CodeNachrufanrufe, die bei Entprellen mit einem Betreff mehrfach ausgeführt werden

//i declare the subject globally 
PublishSubject<Call<List<Response>>> subject = PublishSubject.create(); 

//this is how i call retrofit 
private void updateMarkers(LatLng center) 
{ 
    subject.onNext(new APIHelper(). 
       GetNearByLocations("auth_key", center.latitude, center.longitude, urgency)); 

    subject.debounce(1, TimeUnit.SECONDS) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribeOn(Schedulers.io()) 
       .subscribe(call -> { 
        call.clone().enqueue(new Callback<List<Response>>() 
        { 
         @Override 
         public void onResponse(Call<List<Response>> call, Response<List<Response>> response) 
         { 
          Timber.d("BRAVO!!!"); 
         } 

         @Override 
         public void onFailure(Call<List<Response>> call, Throwable t) 
         { 
          Timber.d("someone's gonna get hurt real bad!!!"); 
         } 
        }); 

       }); 
    } 

Dies ist, was geschieht. Jedes Mal, wenn die updateMarkers() -Methode aufgerufen wird, erstellt Retrofit einen neuen call.clone() und die Anzahl der Aufrufe meines Backends wird jedes Mal um 1 erhöht. Ich habe auch versucht, APIHelper() global zu deklarieren und das gleiche Objekt zu verwenden, um meinen Back-End-Aufruf zu machen. Aber das Ergebnis ist das gleiche. Bitte helfen Sie mir mit einigen Tipps, um dieses Problem zu lösen.

+0

Verschieben Sie das subject.debounce in einer anderen Methode, um einmal in Ihrer Anwendung zu abonnieren (und nicht jedes Mal, wenn Sie updateMakers aufrufen) – dwursteisen

+0

Ich habe es auf onCreate() verschoben, so dass die Methode subject.debounce registriert ist. Gibt es einen besseren Ort, an den ich es verschieben kann? –

+0

onResume? Übrigens, warum Ihr Retrofit-Anruf einen Anruf zurückgibt? Können Sie nicht direkt ein Observable zurückgeben? subject.debonce (1, SEKUNDEN) .flatMap (latLg -> api.getNearbyLocation (latLg.latitude, latLg.longitude)). subscribe(); – dwursteisen

Antwort

2

Im konkreten Fall fügen Sie jedes Mal einen Teilnehmer hinzu, wenn updateMarkers aufgerufen wird.

Um zu erreichen, was Sie wollen, müssen Sie die Erstellung Ihrer beobachtbare in einem anderen Verfahren bewegen müssen, zum Beispiel onResume oder onCreate:

//i declare the subject globally 
PublishSubject<Call<List<Response>>> subject = PublishSubject.create(); 

private void updateMarkers(LatLng center) 
{ 
    subject.onNext(new APIHelper(). 
      GetNearByLocations("auth_key", center.latitude, center.longitude, urgency)); 

} 

@Override 
public void onResume(Context ctx) { 


     subject.debounce(1, TimeUnit.SECONDS) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribeOn(Schedulers.io()) 
      .subscribe(call -> { 
       call.clone().enqueue(new Callback<List<Response>>() 
       { 
        @Override 
        public void onResponse(Call<List<Response>> call, Response<List<Response>> response) 
        { 
         Timber.d("BRAVO!!!"); 
        } 

        @Override 
        public void onFailure(Call<List<Response>> call, Throwable t) 
        { 
         Timber.d("someone's gonna get hurt real bad!!!"); 
        } 
       }); 

      }); 
} 

Bitte beachten Sie, dass Sie Retrofit 2 mit RxJava verwenden können :

Ihre API:

public interface MyApi { 
      Observable<String> getNearByLocation(Double latitude, Double longitude); 
} 

Ihre Aktivität:

+0

Vielen Dank, dass Sie sich die Zeit genommen haben, dies zu schreiben. Als ich versuchte, die beobachtbare Art des Lösens zu verwenden, stieß ich auf die Ausnahme des Hauptthreads im Netzwerk. Ich bin überrascht, warum ich diesen Fehler bekam, obwohl ich auf io thread abonniert hatte. Nachdem ich verschiedene Kombinationen ausprobiert habe, kann ich sehen, dass observeOn, subscribeOn und auch die Debounce-Methode auf Schedulers.io() ausgeführt werden sollten. wird das erwartet? Außerdem wird mein Thema nicht das zweite Mal aufgerufen. Gibt es ein Äquivalent von call.cone(), das ich implementieren muss? –

+0

Auch ich habe noch einen Zweifel. Im Allgemeinen zeige ich processbar, wenn der Anruf zu meinem hinteren Ende gemacht wird und ich höre auf, es zu zeigen, wenn onResponse oder onFailure angerufen wird. In diesem Entprellungsfall muss ich warten, bis meine Entprellzeit abgelaufen ist, und dann beginnen, die Fortschrittsleiste anzuzeigen. Kann ich irgendwie mit dieser Situation umgehen? –

Verwandte Themen