Nachrüstung in RxJava integrieren

1. Übersicht

Dieser Artikel befasst sich mit der Implementierung eines einfachen RxJava-fähigen REST-Clients mithilfe von Retrofit.

Wir werden eine Beispielanwendung erstellen, die mit der GitHub-API interagiert - unter Verwendung des Standard-Retrofit-Ansatzes - und sie dann mit RxJava verbessern, um die Vorteile der reaktiven Programmierung zu nutzen.

2. Einfache Nachrüstung

Lassen Sie uns zunächst ein Beispiel mit Retrofit erstellen. Wir werden die GitHub-APIs verwenden, um eine sortierte Liste aller Mitwirkenden zu erhalten, die mehr als 100 Beiträge in einem Repository haben.

2.1. Maven-Abhängigkeiten

Um ein Projekt mit Retrofit zu starten, fügen wir diese Maven-Artefakte hinzu:

 com.squareup.retrofit2 retrofit 2.3.0   com.squareup.retrofit2 converter-gson 2.3.0 

Die neuesten Versionen finden Sie unter Nachrüstung und Konverter-Gson im Maven Central-Repository.

2.2. API-Schnittstelle

Erstellen wir eine einfache Oberfläche:

public interface GitHubBasicApi { @GET("users/{user}/repos") Call listRepos(@Path("user") String user); @GET("repos/{user}/{repo}/contributors") Call listRepoContributors( @Path("user") String user, @Path("repo") String repo); }

Die Methode listRepos () ruft eine Liste von Repositorys für einen bestimmten Benutzer ab, die als Pfadparameter übergeben wurden .

Die Methode listRepoContributers () ruft eine Liste der Mitwirkenden für einen bestimmten Benutzer und ein bestimmtes Repository ab, die beide als Pfadparameter übergeben werden.

2.3. Logik

Implementieren wir die erforderliche Logik mithilfe von Retrofit Call- Objekten und normalem Java-Code:

class GitHubBasicService { private GitHubBasicApi gitHubApi; GitHubBasicService() { Retrofit retrofit = new Retrofit.Builder() .baseUrl("//api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); gitHubApi = retrofit.create(GitHubBasicApi.class); } List getTopContributors(String userName) throws IOException { List repos = gitHubApi .listRepos(userName) .execute() .body(); repos = repos != null ? repos : Collections.emptyList(); return repos.stream() .flatMap(repo -> getContributors(userName, repo)) .sorted((a, b) -> b.getContributions() - a.getContributions()) .map(Contributor::getName) .distinct() .sorted() .collect(Collectors.toList()); } private Stream getContributors(String userName, Repository repo) { List contributors = null; try { contributors = gitHubApi .listRepoContributors(userName, repo.getName()) .execute() .body(); } catch (IOException e) { e.printStackTrace(); } contributors = contributors != null ? contributors : Collections.emptyList(); return contributors.stream() .filter(c -> c.getContributions() > 100); } }

3. Integration mit RxJava

Retrofit läßt uns Anrufe Ergebnisse mit benutzerdefinierten Handler anstelle der normalen empfangen Anruf Aufgabe durch die Verwendung Retrofit Anruf - Adapters. Dies ermöglicht die Verwendung von RxJava Observables und Flowables hier.

3.1. Maven-Abhängigkeiten

Um den RxJava-Adapter verwenden zu können, müssen wir dieses Maven-Artefakt einschließen:

 com.squareup.retrofit2 adapter-rxjava 2.3.0 

Die neueste Version finden Sie unter adapter-rxjava im zentralen Maven-Repository.

3.2. Registrieren Sie den RxJava-Anrufadapter

Fügen wir dem Builder RxJavaCallAdapter hinzu :

Retrofit retrofit = new Retrofit.Builder() .baseUrl("//api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build();

3.3. API-Schnittstelle

Zu diesem Zeitpunkt können wir den Rückgabetyp der Schnittstellenmethoden so ändern, dass Observable anstelle von Call verwendet wird . Wir können andere Rx-Typen wie Observable , Flowable , Single , Maybe , Completable verwenden .

Ändern wir unsere API-Schnittstelle, um Observable zu verwenden :

public interface GitHubRxApi { @GET("users/{user}/repos") Observable
    
      listRepos(@Path("user") String user); @GET("repos/{user}/{repo}/contributors") Observable
     
       listRepoContributors( @Path("user") String user, @Path("repo") String repo); }
     
    

3.4. Logik

Implementieren wir es mit RxJava:

class GitHubRxService { private GitHubRxApi gitHubApi; GitHubRxService() { Retrofit retrofit = new Retrofit.Builder() .baseUrl("//api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); gitHubApi = retrofit.create(GitHubRxApi.class); } Observable getTopContributors(String userName) { return gitHubApi.listRepos(userName) .flatMapIterable(x -> x) .flatMap(repo -> gitHubApi.listRepoContributors(userName, repo.getName())) .flatMapIterable(x -> x) .filter(c -> c.getContributions() > 100) .sorted((a, b) -> b.getContributions() - a.getContributions()) .map(Contributor::getName) .distinct(); } }

4. Fazit

Beim Vergleich des Codes vor und nach der Verwendung von RxJava haben wir festgestellt, dass er auf folgende Weise verbessert wurde:

  • Reaktiv - Da unsere Daten jetzt in Streams fließen, können wir eine asynchrone Stream-Verarbeitung mit nicht blockierendem Gegendruck durchführen
  • Klar - aufgrund seiner deklarativen Natur
  • Prägnant - Die gesamte Operation kann als eine Operationskette dargestellt werden

Der gesamte Code in diesem Artikel ist auf GitHub verfügbar.

Das Paket com.baeldung.retrofit.basic enthält das grundlegende Nachrüstbeispiel, während das Paket com.baeldung.retrofit. rx enthält das Nachrüstbeispiel mit RxJava-Integration.