Когда использовать RxJava в Android, а когда использовать LiveData от Android Architectural Components?

186

У меня нет причины использовать RxJava в Android и LiveData от Android Architectural Components. Было бы очень полезно, если бы примеры использования и различия между ними были объяснены вместе с примером в виде кода, который объясняет различия между ними.

rahul66
источник
6
Вы нашли хорошую причину еще? Мне интересно то же самое ...
Игорь Ганапольский

Ответы:

117

Android LiveData - это вариант исходного шаблона наблюдателя с добавлением активных / неактивных переходов. Как таковой, он очень ограничен в своем объеме.

Используя пример, описанный в Android LiveData , создается класс для мониторинга данных о местоположении, а также для регистрации и отмены регистрации в зависимости от состояния приложения.

RxJava предоставляет гораздо более обобщенные операторы. Давайте предположим, что эта наблюдаемая будет предоставлять данные о местоположении:

Observable<LocationData> locationObservable;

Реализация наблюдаемой может быть построена с использованием Observable.create()отображения операций обратного вызова. Когда наблюдаемое подписано, обратный вызов регистрируется, а когда он отменяется, обратный вызов не регистрируется. Реализация выглядит очень похоже на код, приведенный в примере.

Предположим также, что у вас есть наблюдаемое, которое выдает истину, когда приложение активно:

Observable<Boolean> isActive;

Затем вы можете предоставить все функциональные возможности LiveData следующим

Observable<LocationData> liveLocation =
  isActive
    .switchMap( active -> active ? locationObservable : Observable.never() );

switchMap()Оператор будет либо обеспечить текущее местоположение в виде потока, или ничего , если приложение не активно. Если у вас есть liveLocationнаблюдаемое, вы можете с ним многое сделать, используя операторы RxJava. Мой любимый пример:

liveLocation.distinctUntilChanged()
  .filter( location -> isLocationInAreaOfInterest( location ) )
  .subscribe( location -> doSomethingWithNewLocation( location ) );

Это будет выполнять действие только тогда, когда местоположение изменилось, и местоположение интересно. Вы можете создавать похожие операции, которые объединяют операторы времени для определения скорости. Что еще более важно, вы можете предоставить подробный контроль над тем, происходят ли операции в основном потоке, или в фоновом потоке, или в нескольких потоках, используя операторы RxJava.

Смысл RxJava в том, что он объединяет управление и синхронизацию в единый юниверс, используя операции, предоставляемые из библиотеки, или даже предоставленные вами пользовательские операции.

LiveData обращается только к одной небольшой части этого юниверса, что эквивалентно построению liveLocation.

Боб Далглиш
источник
2
Спасибо, документы LiveData больше не ссылаются на образец местоположения. Есть более интересные моменты (с примером местоположения) здесь: androidkt.com/livedata
Даниэль Уилсон
5
@DanielWilson ссылка больше не доступна.
Тура
Чувак, я не могу вспомнить, что wtf был по этой ссылке: мне нравится пример кода Марка Эллисона для живых данных: blog.stylingandroid.com/architecture-components-livedata
Даниэль Уилсон
3
The point of RxJava is that it combines control and timing into a single universe, using operations provided from the library, or even custom operations that you provide. Но не осознает жизненный цикл LiveData. Если бы мы использовали Rx, не пришлось бы нам обрабатывать изменения жизненного цикла?
Sparker0i
@ Sparker0i получил здесь точку. RxJava не знает о жизненном цикле. мы должны справиться вручную. где как в LiveData уже позаботился о жизненном цикле.
Aks4125
119

Что касается исходного вопроса, RxJava и LiveData действительно хорошо дополняют друг друга.

LiveDataсветится на слое ViewModel, с его тесной интеграцией с жизненными циклами Android и ViewModel. RxJavaпредоставляет больше возможностей в преобразованиях (как упомянуто @Bob Dalgleish).

В настоящее время мы используем RxJava слои источника данных и хранилища, и он превращается в LiveData(используя LiveDataReactiveStreams) в ViewModels (перед тем, как подвергать данные операциям / фрагментам) - вполне доволен этим подходом.

kzotin
источник
8
Если мы вас правильно поняли, то LiveData полезна только для реализаций пользовательского интерфейса Android. Если мы просто создаем общее приложение с чистой архитектурой и делимся этой архитектурой с другими платформами, то RxJava лучше подходит, чем LiveData?
Игорь Ганапольский
@IgorGanapolsky какой язык / рамки вы используете для универсального приложения?
кзотин
Android-независимые API и Clean Arch написаны на Java / Kotlin.
Игорь Ганапольский
1
Можете ли вы предложить какой-либо рабочий пример LiveDataReactiveStreams в своем ответе?
Паван
2
@ kzotin тебе это не нужно observeOn, LiveDataReactiveStreamsвсе равно это можно сделать, позвонив LiveData.postValue(). И нет никакой гарантии, что у вас subscribeOnбудет какой-либо эффект в целом.
ареколек
77

Есть много различий между LiveData и RxJava:

  1. LiveData не является STREAM, тогда как в RxJava все (буквально все) является STREAM .
  2. LiveData - это наблюдаемый класс держателя данных. В отличие от обычной наблюдаемой, LiveData учитывает жизненный цикл, то есть учитывает жизненный цикл других компонентов приложения, таких как действия, фрагменты или службы. Эта осведомленность гарантирует, что LiveData обновляет только те компоненты приложения, которые находятся в активном жизненном цикле.
  3. LiveData является синхронным , поэтому вы не можете асинхронно выполнять фрагмент кода (сетевой вызов, манипулирование базой данных и т. Д.), Используя только LiveData, как и в RxJava.
  4. Лучшее, что вы можете сделать, чтобы использовать большую часть этого дуэта, это использовать RxJava для вашей бизнес-логики (сетевой вызов, манипулирование данными и т. Д., Все, что происходит в репозитории и за его пределами ) и использовать LiveData для уровня презентации. Таким образом, вы получаете возможности преобразования и потоковой передачи для своей бизнес-логики и операции с учетом жизненного цикла для вашего пользовательского интерфейса.
  5. LiveData и RxJava дополняют друг друга, если используются вместе. Я имею в виду, что все делайте с RxJava, а в конце, когда вы захотите обновить пользовательский интерфейс, сделайте что-то вроде приведенного ниже кода, чтобы изменить Observable на LiveData. Итак, ваш View (UI) наблюдает за LiveData в ViewModel, где ваши LiveData - это не что иное, как неизменяемый MutableLiveData (или MutableLiveData является изменяемым LiveData).
  6. Итак, вопрос в том, почему вы вообще должны использовать LiveData? Как вы можете видеть ниже в коде, вы сохраняете свой ответ из RxJava в MutableLiveData (или LiveData), а ваши LiveData учитывают жизненный цикл, поэтому в некотором смысле ваши данные учитывают жизненный цикл. Теперь представьте себе возможность, когда ваши данные будут знать, когда и когда не обновлять пользовательский интерфейс.
  7. LiveData не имеет истории (только текущее состояние). Следовательно, вы не должны использовать LiveData для приложения чата.
  8. Когда вы используете LiveData с RxJava, вам не нужны такие вещи, как MediatorLiveData , SwitchMap и т. Д. Они являются инструментами управления потоками, и RxJava во многих случаях лучше.
  9. Посмотрите LiveData как вещь держателя данных и ничего больше. Мы также можем сказать, что LiveData является потребителем с учетом жизненного цикла.

    public class RegistrationViewModel extends ViewModel {
        Disposable disposable;

        private RegistrationRepo registrationRepo;
        private MutableLiveData<RegistrationResponse> modelMutableLiveData =
                new MutableLiveData<>();

        public RegistrationViewModel() {
        }

        public RegistrationViewModel(RegistrationRepo registrationRepo) {
            this.registrationRepo = registrationRepo;
        }

        public void init(RegistrationModel registrationModel) {
            disposable = registrationRepo.loginForUser(registrationModel)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<Response<RegistrationResponse>>() {
                        @Override
                        public void accept(Response<RegistrationResponse>
                                                   registrationModelResponse) throws Exception {

                            modelMutableLiveData.setValue(registrationModelResponse.body());
                        }
                    });
        }

        public LiveData<RegistrationResponse> getModelLiveData() {
            return modelMutableLiveData;
        }

       @Override
       protected void onCleared() {
                super.onCleared();
            disposable.dispose();
         }
    }
Абхишек Кумар
источник
5
Посмотрите LiveData как вещь держателя данных и ничего больше. ==> ДА
Лу Морда
3
Хороший пример. Вы забыли объявить одноразовые и было бы неплохо очистить их onCleared.
Сниколас
Не могли бы вы объяснить, как Liveata является синхронным? Насколько я знаю, мы можем отправить объект Livedata другому потоку, а затем этот поток может оценить значение, которое наблюдатель может прослушивать в MainThread.
Хитеш Бишт
Если вы снова прочитаете то, что я написал, это означает, что вы не можете работать над другим потоком просто (ДА, я использовал «просто» даже там), используя LiveData, как вы можете сделать это с помощью RxJava
Абхишек Кумар
Разве жизненный цикл не является большим отличием для LiveData? Вы 1. описываете, что должен делать ваш конвейер, и каковы ваши конечные результаты, 2. подписываетесь на результат в пунктах «наблюдения», И затем 3. конвейер работает, только если это позволяет состояние вашего жизненного цикла.
Srg
29

На самом деле, LiveData это не существенно отличается инструментом RxJava, так почему он был введен в качестве компонента архитектуры , когда RxJavaможно было бы легко управлять жизненным циклом, сохраняя все подписки на наблюдаемых в CompositeDispoable объекте , а затем их утилизации в onDestroy() из Activity или onDestroyView() изFragment , используя только один строка кода?

Я полностью ответил на этот вопрос, создав приложение для поиска фильмов один раз с использованием RxJava, а затем с помощью LiveData здесь .

Короче говоря, да, это возможно, но для этого необходимо сначала переопределить соответствующие методы жизненного цикла, помимо базовых знаний жизненного цикла. Это все еще может не иметь смысла для некоторых, но дело в том, что согласно одному из сеансов Jetpack в Google I / O 2018 многие разработчики находят сложным управление жизненным циклом. Ошибки сбоя, возникающие из-за отсутствия обработки зависимости от жизненного цикла, могут быть еще одним признаком того, что некоторые разработчики, даже не зная жизненного цикла, забывают заботиться об этом в каждой операции / фрагменте, который они используют в своем приложении. В больших приложениях это может стать проблемой, несмотря на негативное влияние, которое это может оказать на производительность.

Суть в том, что благодаря внедрению все LiveDataбольшее число разработчиков, как ожидается, примут MVVM, даже не понимая управления жизненным циклом, утечки памяти и сбоев. Несмотря на то, что я не сомневаюсь, что LiveDataэто не сравнимо с RxJavaточки зрения возможностей и мощности, которую оно дает разработчикам, реактивное программирование и RxJavaявляется трудной для понимания концепцией и инструментом для многих. С другой стороны, я не думаю, что LiveDataэто означает замену RxJava- просто не может - это очень простой инструмент для решения широко распространенной проблемы, с которой сталкиваются многие разработчики.

** ОБНОВЛЕНИЕ ** Я добавил новую статью здесь, где я объяснил, как неправильное использование LiveData может привести к неожиданным результатам. RxJava может прийти на помощь в этих ситуациях


Али Нем
источник
2
«почему это было введено, когда RxJava мог легко управлять жизненным циклом, сохраняя все подписки в CompositeDispoable, а затем размещая их в onDestroy () Действия», - фактически LiveDataуничтожил быonStop
arekolek
@arekolek из моего понимания: даже для обработки CompositeDispoable мы переписали методы жизненного цикла. Но в данных Live все будет включено в одну строку кода. Таким образом, мы сохраняем минимум 20 строк кода.
Суреш
Мы можем определить baseFragment и определить метод Disposable [] subscription (), который будет переопределен всеми производными фрагментами, вызвать этот метод в onCreateView и добавить возвращаемое значение в CompositeDisposable, избавиться от него в onDestroyView, больше не забывая.
android2013
Речь идет не только об утилизации. Используя RxJava, вы должны распорядиться в onStop, затем снова подписаться в onStart / onResume, обработать изменения конфигурации и сделать кучу других вещей. Вот почему так много сбоев с использованием RxJava. LiveData обрабатывает все это, но не так гибко, как RxJava.
user932178
24

Как вы, возможно, знаете, в реактивной экосистеме у нас есть Observable, который испускает данные, и Observer, который подписывается (получает уведомление) об этом Observable излучении, нет ничего странного в том, как работает так называемый паттерн Observer. Наблюдаемый что-то «кричит», Наблюдатель получает уведомление, что Наблюдаемый что-то кричит в данный момент.

Думайте LiveDataкак Наблюдаемый, который позволяет вам управлять Наблюдателями, которые находятся в activeсостоянии. Другими словами LiveData, это простая наблюдаемая, но также заботящаяся о жизненном цикле.

Но давайте посмотрим на два кода, которые вы запрашиваете:

А) Живые данные

Б) RXJava

А) Это базовая реализация LiveData

1) вы обычно создаете экземпляр LiveData в ViewModel для поддержания изменения ориентации (у вас могут быть LiveData, предназначенные только для чтения, или MutableLiveData, доступные для записи, поэтому вы обычно выставляете их вне класса LiveData)

2) в OnCreateметоде Main Activity (не в ViewModel) вы «подписываете» объект Observer (обычно это метод onChanged)

3) вы запускаете метод наблюдения, чтобы установить ссылку

Первый ViewModel(владеет бизнес-логикой)

class ViewModel : ViewModel() { //Point 1

    var liveData: MutableLiveData<Int> = MutableLiveData()

}

И это MainActivity(настолько глупо, насколько это возможно)

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val ViewModelProvider= ViewModelProviders.of(this).get(ViewModel::class.java)

        ViewModelProvider.observe(this, Observer {//Points 2 and 3
            //what you want to observe
        })


        }
    }
}

Б) Это базовая реализация RXJava

1) вы объявляете наблюдаемую

2) вы объявляете наблюдателя

3) вы подписываете Observable с Observer

Observable.just(1, 2, 3, 4, 5, 6) // Point 1

   .subscribe(new Subscriber() {    //Points 2 & 3
       @Override
       public void onCompleted() {
           System.out.println("Complete!");
       }

       @Override
       public void onError(Throwable e) {
       }

       @Override
       public void onNext(Double value) {
           System.out.println("onNext: " + value);
       }
    });

В частности LiveData, используется Lifecycleи часто ViewModel(как мы видели) с компонентами архитектуры. Фактически, когда LiveDataв сочетании с ViewModel позволяет вам обновлять в режиме реального времени каждое изменение в Observer, так что события управляются в режиме реального времени, где это необходимо. Для использования LiveDataнастоятельно рекомендуется знать концепцию жизненного цикла и относительных объектов LifeCycleOwner / LifeCycle , также я бы посоветовал вам взглянуть на преобразования , если вы хотите реализовать их LiveDataв реальных сценариях. Здесь вы можете найти несколько вариантов использования от большого общего программного обеспечения .

Заключение в основномLiveDataупрощенныйRXJava, элегантный способ наблюдать за изменениями в нескольких компонентах без создания явных так называемых правил зависимости между компонентами, чтобы вы могли намного проще протестировать код и сделать его намного более читабельным. RXJava, позволяет вам делать вещи LiveData и многое другое. Из-за расширенных функциональных возможностей RXJava вы можете использовать LiveData для простых случаев или использовать всю мощь RXJava, продолжая использовать компоненты архитектуры Android в качестве ViewModel , конечно, это означает, что этоRXJavaможет быть гораздо более сложным, просто подумайте, что вместо этого есть сотни операторов SwitchMap и Карта LiveData (на данный момент).

RXJava версии 2 - это библиотека, которая произвела революцию в объектно-ориентированной парадигме, добавив так называемый функциональный способ управления потоком программ.

trocchietto
источник
4

LiveData - это подмножество компонентов архитектуры Android, разработанных командой Android.

С текущими данными и другими компонентами архитектуры утечки памяти и другие подобные проблемы решаются компонентами архитектуры. Так как он разработан командой Android, он является лучшим для Android. Они также предоставляют обновления для новых версий Android.

Если вы хотите использовать только при разработке приложений для Android, перейдите на компоненты архитектуры Android. В противном случае, если вы хотите использовать другое приложение Java, такое как веб-приложение, настольные приложения и т. Д., Используйте RxJava

SIVAKUMAR.J
источник
Я попытался уточнить ваш ответ. Если я каким-либо образом вступил в конфликт с вашим первоначальным намерением, не стесняйтесь редактировать. Если вы все же сделаете это, пожалуйста, попробуйте сделать его более понятным, чем первоначальная версия. Последняя часть вашего ответа, честно говоря, не имеет смысла.
Зоя
2

LiveDataкак вещь держателя данных и ничего больше. Можно также сказать, что LiveData - потребитель, осведомленный о жизненном цикле. LiveDataНастоятельно рекомендуется знать концепцию жизненного цикла и относительных объектов LifeCycleOwner / LifeCycle, вы получаете возможности преобразования и потоковой передачи для своей бизнес-логики и операции с учетом жизненного цикла для вашего пользовательского интерфейса.

Rx - это мощный инструмент, который позволяет решить проблему в элегантном декларативном стиле. Он обрабатывает бизнес-параметры или операции Service Api

Attif
источник
0

Сравнение LiveData с RxJava - это сравнение яблок с фруктовыми салатами.

Сравните LiveData с ContentObserver, и вы сравниваете яблоки с яблоками. LiveData фактически является заменой ContentObserver с учетом жизненного цикла.

Сравнение RxJava с AsyncTask или любым другим инструментом для нарезки сравнивает фруктовые салаты с апельсинами, потому что RxJava помогает не только нарезать потоки.

straya
источник
0
  • LiveData частично равен Rx Subject или SharedRxObservable

  • LiveData управляет жизненным циклом подписки, но подписка Rx Subject должна быть создана и удалена вручную

  • LiveData не имеет состояния завершения, но Rx Subject имеет OnError и OnCompleted

Сергей М
источник