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.