Nachrüstung mit RxJava integrieren

Nachrüstung mit RxJava integrieren

1. Überblick

Dieser Artikel befasst sich mit der Implementierung eines einfachenRxJava-ready REST-Clients mitRetrofit.

Wir werden eine Beispielanwendung erstellen, die mit der GitHub-API interagiert - unter Verwendung des Standard-Retrofit-Ansatzes - und sie dann mithilfe von 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 verwenden die GitHub-APIs, 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 folgende Maven-Artefakte hinzu:


    com.squareup.retrofit2
    retrofit
    2.3.0



    com.squareup.retrofit2
    converter-gson
    2.3.0

Die neuesten Versionen finden Sie unterretrofit undconverter-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 MethodelistRepos() ruft eine Liste von Repositorys für einen bestimmten Benutzer ab, die als Pfadparameter übergeben wurden.

Die MethodelistRepoContributers()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 der Objekte von RetrofitCallund normalem Java-Code:

class GitHubBasicService {

    private GitHubBasicApi gitHubApi;

    GitHubBasicService() {
        Retrofit retrofit = new Retrofit.Builder()
          .baseUrl("https://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 in RxJava

Mit Retrofit können wir Anrufergebnisse mit benutzerdefinierten Handlern anstelle des normalenCall-Objekts empfangen, indem wir die Adapter von RetrofitCallverwenden. Dies ermöglicht es, hier RxJavaObservables undFlowables zu verwenden.

3.1. Maven-Abhängigkeiten

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


    com.squareup.retrofit2
    adapter-rxjava
    2.3.0

Für die neueste Version überprüfen Sie bitteadapter-rxjava im zentralen Maven-Repository.

3.2. Registrieren Sie den RxJava-Anrufadapter

Fügen wir dem BuilderRxJavaCallAdapter hinzu:

Retrofit retrofit = new Retrofit.Builder()
  .baseUrl("https://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 ändern, umObservable<…> anstelle vonCall<…> zu verwenden. Wir können andere Rx-Typen wieObservable,Flowable,Single,Maybe,Completable verwenden.

Ändern Sie unsere API-Schnittstelle so, dassObservable verwendet werden:

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("https://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 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 inover on GitHub. verfügbar

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