1. Общ преглед
Тази статия се фокусира върху това как да внедрите прост RXJava-готов REST клиент, използващ Retrofit.
Ще създадем примерно приложение, взаимодействащо с API на GitHub - използвайки стандартния подход за модернизация и след това ще го подобрим с помощта на RxJava, за да използваме предимствата на реактивното програмиране.
2. Обикновена модернизация
Нека първо изградим пример с Retrofit. Ще използваме API на GitHub, за да получим сортиран списък на всички сътрудници, които имат повече от 100 приноса във всяко хранилище.
2.1. Зависимости на Maven
За да започнем проект с модернизация, нека включим тези артефакти на Maven:
com.squareup.retrofit2 retrofit 2.3.0 com.squareup.retrofit2 converter-gson 2.3.0
За най-новите версии погледнете модернизацията и конвертора-gson в хранилището на Maven Central.
2.2. API интерфейс
Нека създадем прост интерфейс:
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); }
Методът listRepos () извлича списък с хранилища за даден потребител, предаден като параметър на пътя.
Методът listRepoContributers () извлича списък на сътрудници за даден потребител и хранилище, и двете предадени като параметри на пътя.
2.3. Логика
Нека внедрим необходимата логика, като използваме обекти за модернизиране на обаждания и нормален Java код:
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. Интегриране с RxJava
Модернизацията ни позволява да получаваме резултати от обаждания с персонализирани манипулатори вместо обичайния обект на повикване, като използваме адаптери за модернизиране на повиквания . Това дава възможност да се използва RxJava наблюдаеми и Течните тук.
3.1. Зависимости на Maven
За да използваме адаптер RxJava, трябва да включим този артефакт на Maven:
com.squareup.retrofit2 adapter-rxjava 2.3.0
За най-новата версия, моля, проверете adapter-rxjava в централното хранилище на Maven.
3.2. Регистрирайте RxJava Call Adapter
Нека добавим RxJavaCallAdapter към конструктора:
Retrofit retrofit = new Retrofit.Builder() .baseUrl("//api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build();
3.3. API интерфейс
На този етап можем да променим типа на връщане на метода на интерфейса, за да използваме Observable, а не Call . Можем да използваме други Rx типове като Observable , Flowable , Single , Maybe , Completable .
Нека модифицираме нашия интерфейс на API, за да използваме Observable :
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. Логика
Нека го приложим с помощта на 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. Заключение
Сравнявайки кода преди и след използване на RxJava, установихме, че той е подобрен по следните начини:
- Реактивен - тъй като данните ни сега текат в потоци, това ни позволява да извършваме асинхронна обработка на потоци с неблокиращо обратно налягане
- Ясно - поради декларативния му характер
- Кратко - цялата операция може да бъде представена като една операционна верига
Целият код в тази статия е достъпен в GitHub.
Пакетът com.baeldung.retrofit.basic съдържа основния пример за модернизация, докато пакетът com.baeldung.retrofit. rx съдържа примера за модернизация с интеграция на RxJava.