Я работаю над созданием сетей для моего приложения. Поэтому я решил попробовать Square чрезвычайно Дооснащение . Я вижу, что они поддерживают простыеCallback
@GET("/user/{id}/photo")
void getUserPhoto(@Path("id") int id, Callback<Photo> cb);
и RxJava's Observable
@GET("/user/{id}/photo")
Observable<Photo> getUserPhoto(@Path("id") int id);
На первый взгляд оба выглядят довольно схожими, но когда дело доходит до реализации, становится интересно ...
Хотя с простой реализацией обратного вызова будет выглядеть примерно так:
api.getUserPhoto(photoId, new Callback<Photo>() {
@Override
public void onSuccess() {
}
});
что довольно просто и понятно. И с Observable
этим быстро становится многословным и довольно сложным.
public Observable<Photo> getUserPhoto(final int photoId) {
return Observable.create(new Observable.OnSubscribeFunc<Photo>() {
@Override
public Subscription onSubscribe(Observer<? super Photo> observer) {
try {
observer.onNext(api.getUserPhoto(photoId));
observer.onCompleted();
} catch (Exception e) {
observer.onError(e);
}
return Subscriptions.empty();
}
}).subscribeOn(Schedulers.threadPoolForIO());
}
И это не так. Вы все еще должны сделать что-то вроде этого:
Observable.from(photoIdArray)
.mapMany(new Func1<String, Observable<Photo>>() {
@Override
public Observable<Photo> call(Integer s) {
return getUserPhoto(s);
}
})
.subscribeOn(Schedulers.threadPoolForIO())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Photo>() {
@Override
public void call(Photo photo) {
//save photo?
}
});
Я что-то здесь упускаю? Или это неправильный случай использования Observable
s? Когда предпочтение будет Observable
отдано простому Обратному звонку?
Обновить
Использовать модернизацию намного проще, чем в примере выше, как показал @Niels в своем ответе или в примере проекта Джейка Уортона U2020 . Но по сути вопрос остается неизменным - когда один должен использовать один или другой?
Ответы:
Для простых сетевых вещей преимущества RxJava перед Callback очень ограничены. Простой пример getUserPhoto:
RxJava:
Перезвони:
Вариант RxJava не намного лучше, чем вариант Callback. А пока давайте проигнорируем обработку ошибок. Давайте возьмем список фотографий:
RxJava:
Перезвони:
Теперь вариант RxJava все еще не меньше, хотя с Lambdas он будет ближе к варианту Callback. Кроме того, если у вас есть доступ к каналу JSON, было бы странно получить все фотографии, когда вы только отображаете PNG. Просто настройте подачу, чтобы на ней отображались только PNG.
Первый вывод
Это не делает вашу кодовую базу меньше, когда вы загружаете простой JSON, который вы подготовили в нужном формате.
Теперь давайте сделаем вещи немного интереснее. Допустим, вы не только хотите получить userPhoto, но у вас есть клон Instagram, и вы хотите получить 2 JSON: 1. getUserDetails () 2. getUserPhotos ()
Вы хотите загрузить эти два JSON параллельно, и когда оба будут загружены, страница должна отображаться. Вариант обратного вызова станет немного сложнее: вам нужно создать 2 обратных вызова, сохранить данные в упражнении и, если все данные загружены, отобразить страницу:
Перезвони:
RxJava:
Мы куда-то добираемся! Код RxJava теперь такой же большой, как и опция обратного вызова. Код RxJava является более надежным; Подумайте, что произойдет, если нам понадобится загрузить третий JSON (например, последние видео)? RxJava потребуется только небольшая настройка, в то время как вариант Callback должен быть настроен в нескольких местах (при каждом обратном вызове мы должны проверять, все ли данные получены).
Другой пример; мы хотим создать поле автозаполнения, которое загружает данные с помощью Retrofit. Мы не хотим делать веб-вызовы каждый раз, когда EditText имеет TextChangedEvent. При быстрой печати только последний элемент должен инициировать вызов. На RxJava мы можем использовать оператор debounce:
Я не буду создавать вариант обратного вызова, но вы поймете, что это гораздо больше работы.
Вывод: RxJava исключительно хорош, когда данные отправляются в виде потока. Retrofit Observable помещает все элементы в поток одновременно. Это не особенно полезно само по себе по сравнению с Callback. Но когда в поток помещается несколько элементов и в разное время, и вам нужно делать вещи, связанные с синхронизацией, RxJava делает код более понятным.
источник
inputObservable
? У меня много проблем с разоблачением, и я хотел бы узнать немного больше об этом решении.RxView
иRxTextView
т. Д., Которые можно использовать дляinputObservable
.Наблюдаемые вещи уже сделаны в Retrofit, поэтому код может быть таким:
источник
Callback
вы можете отказатьсяObserveable
, поэтому избегаете распространенных проблем жизненного цикла.В случае getUserPhoto () преимущества для RxJava невелики. Но давайте рассмотрим другой пример, когда вы получите все фотографии для пользователя, но только когда изображение имеет формат PNG, и у вас нет доступа к JSON для выполнения фильтрации на стороне сервера.
Теперь JSON возвращает список фотографий. Мы будем составлять карту для отдельных предметов. Таким образом, мы сможем использовать метод фильтра, чтобы игнорировать фотографии, которые не являются PNG. После этого мы подпишемся и получим обратный вызов для каждой отдельной фотографии, errorHandler и обратный вызов, когда все строки будут завершены.
TLDR Точка здесь существо; обратный вызов только возвращает вам обратный вызов для успеха и неудачи; RxJava Observable позволяет вам делать карту, уменьшать, фильтровать и многое другое.
источник
С rxjava вы можете делать больше с меньшим количеством кода.
Предположим, вы хотите реализовать мгновенный поиск в своем приложении. С помощью обратных вызовов вы беспокоитесь о том, чтобы отписаться от предыдущего запроса и подписаться на новый, самостоятельно справиться с изменением ориентации ... Я думаю, что это много кода и слишком многословно.
С rxjava все очень просто.
если вы хотите реализовать мгновенный поиск, вам нужно только прослушать TextChangeListener и вызвать
photoModel.setUserId(EditText.getText());
В методе OnCreate фрагмента или действия вы подписываетесь на Observable, который возвращает photoModel.subscribeToPhoto (), он возвращает Observable, который всегда испускает элементы, испускаемые последним Observable (запросом).
Кроме того, если PhotoModel является, например, Singleton, вам не нужно беспокоиться об изменении ориентации, потому что BehaviorSubject выдает последний ответ сервера, независимо от того, когда вы подписались.
С помощью этих строк кода мы реализовали мгновенный поиск и изменили ориентацию. Как вы думаете, вы можете реализовать это с помощью обратных вызовов с меньшим количеством кода? Я сомневаюсь в этом.
источник
Обычно мы используем следующую логику:
источник
По примерам и выводам в других ответах, я думаю, нет большой разницы для простых одно или двухэтапных задач. Однако Обратный звонок прост и понятен. RxJava более сложный и слишком большой для простой задачи. Существует третье решение: AbacusUtil . Позвольте мне реализовать описанные выше варианты использования со всеми тремя решениями: Callback, RxJava, CompletableFuture (AbacusUtil) с Retrolambda :
Получить фотографию из сети и сохранить / отобразить на устройстве:
Загрузка пользовательских данных и фото параллельно
источник
Лично я предпочитаю использовать Rx для получения ответов API в тех случаях, когда мне нужно выполнить фильтрацию, сопоставление или что-то подобное с данными или в случаях, когда мне нужно выполнить другие вызовы API на основе предыдущих ответов на вызовы.
источник
Похоже, что вы изобретаете велосипед, то, что вы делаете, уже реализовано в модернизации.
Например, вы можете взглянуть на RestAdapterTest.java , где они определяют интерфейс с Observable в качестве возвращаемого типа, а затем использовать его .
источник
Когда вы создаете приложение для развлечения, проект питомца, POC или первый прототип, вы используете простые базовые классы android / java, такие как обратные вызовы, асинхронные задачи, циклы, потоки и т. Д. Они просты в использовании и не требуют каких-либо Интеграция сторонних библиотек. Интеграция большой библиотеки просто для создания небольшого неизменного проекта нелогична, когда нечто подобное можно сделать прямо из рук вон.
Однако это как очень острый нож. Использование их в производственной среде всегда здорово, но они также будут иметь последствия. Трудно написать безопасный параллельный код, если вы не разбираетесь в принципах чистого кодирования и принципах SOLID. Вам нужно будет поддерживать правильную архитектуру, чтобы облегчить будущие изменения и повысить производительность команды.
С другой стороны, библиотеки параллелизма, такие как RxJava, Co-рутины и т. Д., Проверяются и проверяются более миллиарда раз, чтобы помочь в написании готового параллельного кода. Опять же, дело не в том, что используя эти библиотеки, вы не пишете параллельный код или абстрагируете всю логику параллелизма. Вы все еще. Но теперь он видим и обеспечивает четкую схему написания параллельного кода для всей кодовой базы и, что более важно, для всей вашей команды разработчиков.
Это является основным преимуществом использования инфраструктуры параллелизма вместо простых старых базовых классов, которые имеют дело с необработанным параллелизмом. Однако не поймите меня неправильно. Я твердо верю в ограничение зависимостей внешней библиотеки, но в этом конкретном случае вам придется создать собственную платформу для вашей кодовой базы, которая является трудоемкой задачей и может быть выполнена только после предварительного опыта. Следовательно, среды параллелизма предпочтительнее, чем простые классы, такие как обратные вызовы и т. Д.
TL'DR
Если вы уже используете RxJava для одновременного кодирования по всей базе кода, просто используйте RxJava Observable / Flowable. Мудрый вопрос, который нужно задать, - использовать ли Observables для Flowables. Если нет, то иди и используй вызываемый.
источник