Для простих мережних матеріалів переваги RxJava перед зворотним зворотом дуже обмежені. Простий приклад getUserPhoto:
RxJava:
api.getUserPhoto(photoId)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Photo>() {
@Override
public void call(Photo photo) {
// do some stuff with your photo
}
});
Зворотний виклик:
api.getUserPhoto(photoId, new Callback<Photo>() {
@Override
public void onSuccess(Photo photo, Response response) {
}
});
Варіант RxJava не набагато кращий, ніж варіант Callback. Поки що ігноруємо обробку помилок. Візьмемо список фотографій:
RxJava:
api.getUserPhotos(userId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMap(new Func1<List<Photo>, Observable<Photo>>() {
@Override
public Observable<Photo> call(List<Photo> photos) {
return Observable.from(photos);
}
})
.filter(new Func1<Photo, Boolean>() {
@Override
public Boolean call(Photo photo) {
return photo.isPNG();
}
})
.subscribe(
new Action1<Photo>() {
@Override
public void call(Photo photo) {
list.add(photo)
}
});
Зворотний виклик:
api.getUserPhotos(userId, new Callback<List<Photo>>() {
@Override
public void onSuccess(List<Photo> photos, Response response) {
List<Photo> filteredPhotos = new ArrayList<Photo>();
for(Photo photo: photos) {
if(photo.isPNG()) {
filteredList.add(photo);
}
}
}
});
Тепер варіант RxJava все ще не менший, хоча з Lambdas він буде ближче до варіанту Callback. Крім того, якщо у вас є доступ до каналу JSON, було б дивним отримати всі фотографії, коли ви показуєте лише PNG. Просто налаштуйте канал, щоб він відображав лише PNG.
Перший висновок
Це не робить вашу базу коду меншою, коли ви завантажуєте простий JSON, який ви підготували до правильного формату.
Тепер давайте зробимо речі трохи цікавішими. Скажімо, ви не тільки хочете отримати userPhoto, але у вас є Instagram-клон, і ви хочете отримати 2 JSON: 1. getUserDetails () 2. getUserPhotos ()
Ви хочете завантажити ці два JSON паралельно, і коли вони завантажуються, сторінка повинна відображатися. Варіант зворотного дзвінка стане дещо складнішим: вам потрібно створити 2 зворотні дзвінки, зберігати дані в діяльності, а якщо всі дані завантажені, відобразити сторінку:
Зворотний виклик:
api.getUserDetails(userId, new Callback<UserDetails>() {
@Override
public void onSuccess(UserDetails details, Response response) {
this.details = details;
if(this.photos != null) {
displayPage();
}
}
});
api.getUserPhotos(userId, new Callback<List<Photo>>() {
@Override
public void onSuccess(List<Photo> photos, Response response) {
this.photos = photos;
if(this.details != null) {
displayPage();
}
}
});
RxJava:
private class Combined {
UserDetails details;
List<Photo> photos;
}
Observable.zip(api.getUserDetails(userId), api.getUserPhotos(userId), new Func2<UserDetails, List<Photo>, Combined>() {
@Override
public Combined call(UserDetails details, List<Photo> photos) {
Combined r = new Combined();
r.details = details;
r.photos = photos;
return r;
}
}).subscribe(new Action1<Combined>() {
@Override
public void call(Combined combined) {
}
});
Ми кудись дістаємось! Код RxJava тепер такий же великий, як і варіант зворотного дзвінка. Код RxJava є більш надійним; Подумайте, що буде, якби нам був потрібен третій JSON для завантаження (як останні відеоролики)? RxJava потребує лише невеликого регулювання, тоді як варіант зворотного виклику повинен бути відрегульований у декількох місцях (для кожного зворотного дзвінка нам потрібно перевірити, чи отримано всі дані).
Ще один приклад; ми хочемо створити поле автозаповнення, яке завантажує дані за допомогою Retrofit. Ми не хочемо робити веб-дзвінок щоразу, коли редактор тексту має TextChangedEvent. Коли ви швидко набираєте текст, лише останній елемент повинен викликати дзвінок. На RxJava ми можемо використовувати оператор дебютування:
inputObservable.debounce(1, TimeUnit.SECONDS).subscribe(new Action1<String>() {
@Override
public void call(String s) {
// use Retrofit to create autocompletedata
}
});
Я не буду створювати варіант зворотного виклику, але ви зрозумієте, що це набагато більше роботи.
Висновок: RxJava надзвичайно хороший, коли дані надсилаються як потік. Модуль модернізації одночасно виштовхує всі елементи на потоці. Це само по собі не є корисним порівняно з зворотним викликом. Але коли в потоці є декілька елементів, що висуваються в різні часи, і вам потрібно робити речі, пов’язані з тимчасовим часом, RxJava робить код набагато більш ретельним.