Wann sollte RxJava in Android verwendet werden und wann sollte LiveData von Android Architectural Components verwendet werden?


185

Ich bekomme keinen Grund, RxJava in Android und LiveData von Android Architectural Components zu verwenden. Es wäre sehr hilfreich, wenn die Anwendungsfälle und Unterschiede zwischen beiden zusammen mit einem Beispielbeispiel in Form von Code erläutert würden, der die Unterschiede zwischen beiden erklärt.


5
Hast du schon einen guten Grund gefunden? Ich frage mich das gleiche ...
IgorGanapolsky

Antworten:


117

Android LiveData ist eine Variante des ursprünglichen Beobachtermusters mit zusätzlichen aktiven / inaktiven Übergängen. Als solches ist es in seinem Umfang sehr restriktiv.

Anhand des in Android LiveData beschriebenen Beispiels wird eine Klasse erstellt, um Standortdaten zu überwachen und die Registrierung basierend auf dem Anwendungsstatus zu registrieren und die Registrierung aufzuheben .

RxJava bietet Operatoren, die viel allgemeiner sind. Nehmen wir an, dass dieses Observable Standortdaten liefert:

Observable<LocationData> locationObservable;

Die Implementierung des Observable kann mithilfe Observable.create()der Abbildung der Rückrufoperationen aufgebaut werden. Wenn das Observable abonniert ist, wird der Rückruf registriert, und wenn es abgemeldet ist, wird der Rückruf nicht registriert. Die Implementierung sieht dem im Beispiel bereitgestellten Code sehr ähnlich.

Nehmen wir außerdem an, dass Sie ein Observable haben, das true ausgibt, wenn die Anwendung aktiv ist:

Observable<Boolean> isActive;

Anschließend können Sie alle Funktionen von LiveData wie folgt bereitstellen

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

Der switchMap()Bediener gibt entweder den aktuellen Standort als Stream an oder nichts, wenn die Anwendung nicht aktiv ist. Sobald Sie das liveLocationObservable haben, können Sie mit RxJava-Operatoren viele Dinge damit tun. Mein Lieblingsbeispiel ist:

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

Dadurch wird die Aktion nur ausgeführt, wenn sich der Standort geändert hat und der Standort interessant ist. Sie können ähnliche Operationen erstellen, die Zeitoperatoren kombinieren, um die Geschwindigkeit zu bestimmen. Noch wichtiger ist, dass Sie mithilfe von RxJava-Operatoren detailliert steuern können, ob Vorgänge im Hauptthread, im Hintergrundthread oder in mehreren Threads ausgeführt werden.

Der Punkt von RxJava ist, dass es Steuerung und Timing in einem einzigen Universum kombiniert, indem Operationen verwendet werden, die aus der Bibliothek bereitgestellt werden, oder sogar benutzerdefinierte Operationen, die Sie bereitstellen.

LiveData adressiert nur einen kleinen Teil dieses Universums, was dem Aufbau des Universums entspricht liveLocation.


2
Vielen Dank, die LiveData-Dokumente scheinen nicht mehr auf ein Standortbeispiel zu verweisen. Es gibt weitere interessante Punkte (mit einem Standortbeispiel) hier: androidkt.com/livedata
Daniel Wilson

5
@ DanielWilson Der Link ist nicht mehr verfügbar.
Tura

Alter, ich kann mich nicht erinnern, dass wtf auf diesem Link war: DI wie Mark Allisons Beispielcode für Live-Daten: blog.stylingandroid.com/architecture-components-livedata
Daniel Wilson

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. Ist der LiveData-Lebenszyklus jedoch nicht bekannt? Wenn wir Rx verwenden würden, müssten wir dann nicht die Änderungen des Lebenszyklus bewältigen?
Sparker0i

@ Sparker0i hat hier Punkt. RxJava ist nicht lebenszyklusbewusst. wir müssen manuell handhaben. wo wie in LiveData bereits für den Lebenszyklus gesorgt ist.
Aks4125

119

In Bezug auf die ursprüngliche Frage ergänzen sich sowohl RxJava als auch LiveData sehr gut.

LiveDataglänzt auf der ViewModel-Ebene mit ihrer engen Integration in Android-Lebenszyklen und ViewModel. RxJavabietet mehr Funktionen bei Transformationen (wie von @Bob Dalgleish erwähnt).

Derzeit verwenden wir RxJavaDatenquellen- und Repository-Ebenen und sie LiveDatawerden LiveDataReactiveStreamsin ViewModels in (using ) umgewandelt (bevor Daten Aktivitäten / Fragmenten ausgesetzt werden) - sehr zufrieden mit diesem Ansatz.


8
Wenn wir Sie richtig verstanden haben, ist LiveData nur für Android-UI-spezifische Implementierungen nützlich. Wenn wir nur eine generische App mit Clean Architecture erstellen und diese Architektur mit anderen Plattformen teilen, passt RxJava besser als LiveData?
Igor Ganapolsky

@IgorGanapolsky Welche Sprache / Frameworks verwenden Sie für generische Apps?
Kzotin

Android-unabhängige APIs und Clean Arch in Java / Kotlin geschrieben.
Igor Ganapolsky

1
Können Sie in Ihrer Antwort ein funktionierendes Beispiel für LiveDataReactiveStreams vorschlagen?
Pawan

2
@kzotin Sie , dass Sie nicht brauchen observeOn, LiveDataReactiveStreamsgeht das sowieso durch den Aufruf LiveData.postValue(). Und es gibt keine Garantie dafür, dass Ihr subscribeOnWille generell Auswirkungen hat.
Arekolek

77

Es gibt viele Unterschiede zwischen LiveData und RxJava:

  1. LiveData ist kein STREAM während in RxJava alles (buchstäblich alles) ein STREAM ist .
  2. LiveData ist eine beobachtbare Datenhalterklasse. Im Gegensatz zu einem regulären Observable ist LiveData lebenszyklusabhängig, dh es berücksichtigt den Lebenszyklus anderer App-Komponenten wie Aktivitäten, Fragmente oder Dienste. Diese Kenntnis stellt sicher, dass LiveData nur Beobachter von App-Komponenten aktualisiert, die sich in einem aktiven Lebenszyklus befinden.
  3. LiveData ist synchron , Sie einen Codeabschnitt (Netzwerkaufruf, Datenbankmanipulation usw.) nicht asynchron ausführen können, indem Sie nur LiveData verwenden, wie Sie es mit RxJava tun.
  4. Was Sie am besten tun können, um das Beste aus diesem Duo herauszuholen, ist die Verwendung von RxJava für Ihre Geschäftslogik (Netzwerkaufruf, Datenmanipulation usw.), alles, was im und außerhalb des Repositorys geschieht ) zu verwenden und LiveData für Ihre Präsentationsebene zu verwenden. Auf diese Weise erhalten Sie Transformations- und Stream-Funktionen für Ihre Geschäftslogik und einen lebenszyklusbewussten Betrieb für Ihre Benutzeroberfläche.
  5. LiveData und RxJava ergänzen sich, wenn sie zusammen verwendet werden. Ich meine, machen Sie alles mit RxJava und machen Sie am Ende, wenn Sie die Benutzeroberfläche aktualisieren möchten, etwas wie den unten angegebenen Code, um Ihr Observable in LiveData zu ändern. Ihre View (UI) beobachtet also die LiveData in ViewModel, wobei Ihre LiveData nichts anderes als nicht veränderbare MutableLiveData sind (oder MutableLiveData veränderbare LiveData sind).
  6. Die Frage hier ist also, warum Sie LiveData überhaupt verwenden sollten. Wie Sie unten im Code sehen können, speichern Sie Ihre Antwort von RxJava an MutableLiveData (oder LiveData) und Ihre LiveData sind lebenszyklusabhängig, sodass Ihre Daten in gewisser Weise lebenszyklusabhängig sind. Stellen Sie sich nun die Möglichkeit vor, wenn Ihre Daten selbst wissen, wann und wann die Benutzeroberfläche nicht aktualisiert werden muss.
  7. LiveData hat keinen Verlauf (nur den aktuellen Status). Daher sollten Sie LiveData nicht für eine Chat-Anwendung verwenden.
  8. Wenn Sie LiveData mit RxJava verwenden, benötigen Sie keine Inhalte wie MediatorLiveData oder SwitchMap usw. Sie sind Tools zur Stream-Steuerung, und RxJava ist um ein Vielfaches besser darin.
  9. Sehen Sie LiveData als Datenhalter und sonst nichts. Wir können auch sagen, dass LiveData ein lebenszyklusbewusster Verbraucher ist.

    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
Sehen Sie LiveData als Datenhalter und sonst nichts. ==> JA
Lou Morda

3
Schönes Beispiel. Sie haben vergessen, das Einwegprodukt zu deklarieren, und es wäre schön, es einzuräumen onCleared.
Snicolas

Könnten Sie bitte erklären, wie Livedata synchron ist? Soweit ich weiß, können wir das Livedata-Objekt an einen anderen Thread senden, und dieser Thread kann dann einen Nachwert angeben, den der Beobachter im MainThread abhören kann.
Hitesh Bisht

Wenn Sie noch einmal lesen, was ich geschrieben habe, bedeutet dies, dass Sie nicht einfach mit LiveData an einem anderen Thread arbeiten können (JA, ich habe "nur" verwendet), wie Sie es mit RxJava
Abhishek Kumar am

Ist der Lebenszyklus nicht ein großes Unterscheidungsmerkmal für LiveData? Sie 1. beschreiben, was Ihre Pipeline tun muss und was Ihre Endergebnisse sind, 2. abonnieren das Ergebnis in "Beobachten" -Klauseln und 3. dann wird die Pipeline nur betrieben, wenn Ihr Lebenszyklus dies zulässt.
Srg

29

Tatsächlich LiveData handelt es sich nicht um ein wesentlich anderes Tool als das RxJava, weshalb es als Architekturkomponente eingeführt wurde, wenn RxJavader Lebenszyklus leicht hätte verwaltet werden können, indem alle Abonnements für Observable in einem CompositeDispoable Objekt gespeichert und dann in onDestroy() das Activity oder onDestroyView() desFragment nur eines verwendet wurden Codezeile?

Ich habe diese Frage vollständig beantwortet, indem ich eine Filmsuch-App einmal mit RxJava und dann mit LiveData hier erstellt habe .

Kurz gesagt, ja, das könnte es, aber dafür müssten zunächst die relevanten Lebenszyklusmethoden außer dem grundlegenden Lebenszykluswissen außer Kraft gesetzt werden. Dies mag für einige immer noch keinen Sinn ergeben, aber die Tatsache ist, dass nach einem der Jetpack-Sitzungen in Google I / O 2018 viele Entwickler den Lebenszyklusmanagementkomplex als komplex empfinden. Die Absturzfehler, die dadurch entstehen, dass die Abhängigkeit vom Lebenszyklus nicht behandelt wird, können ein weiteres Zeichen dafür sein, dass einige Entwickler, auch wenn sie sich mit dem Lebenszyklus auskennen, vergessen, dies in jeder Aktivität / jedem Fragment zu berücksichtigen, die sie in ihrer App verwenden. In großen Apps kann dies trotz der negativen Auswirkungen auf die Produktivität zu einem Problem werden.

Unter dem Strich wird von einer LiveDatagrößeren Anzahl von Entwicklern erwartet, dass sie MVVM einführen , ohne das Lebenszyklusmanagement, den Speicherverlust und den Absturz verstehen zu müssen. Auch wenn ich keinen Zweifel daran habe, dass dies in Bezug auf die Fähigkeiten und die Leistung, die es Entwicklern bietet , LiveDatanicht vergleichbar ist RxJava, ist die reaktive Programmierung RxJavafür viele ein schwer verständliches Konzept und Werkzeug. Auf der anderen Seite denke ich nicht, LiveDatadass es ein Ersatz für sein sollRxJava - es kann einfach nicht - sein soll, sondern ein sehr einfaches Werkzeug zur Behandlung eines umstrittenen, weit verbreiteten Problems, das bei vielen Entwicklern auftritt.

** UPDATE ** Ich habe hier einen neuen Artikel hinzugefügt , in dem ich erklärt habe, wie der Missbrauch von LiveData zu unerwarteten Ergebnissen führen kann. RxJava kann in diesen Situationen zur Rettung kommen



2
„Warum war es eingeführt wird, wenn RxJava leicht den Lebenszyklus alle Abonnements geschafft haben , konnten in einem CompositeDispoable durch Speichern und sie dann in onDestroy () der Aktivität Entsorgung“ - LiveDataentsorgen würde onStoptatsächlich
arekolek

@arekolek aus meinem Verständnis: Selbst um das CompositeDispoable zu handhaben, haben wir die Lebenszyklusmethoden überschrieben. In Live-Daten werden jedoch alle in einer einzigen Codezeile enthalten sein. Wir sparen also mindestens 20 Codezeilen.
Suresh

Wir können ein baseFragment definieren und die Methode Disposable [] subscriptions () definieren, die von allen abgeleiteten Fragmenten überschrieben werden soll. Rufen Sie diese Methode in onCreateView auf und fügen Sie den Rückgabewert in CompositeDisposable hinzu. Entsorgen Sie diesen in onDestroyView, ohne mehr zu vergessen.
android2013

Es geht nicht nur um Entsorgung. Mit RxJava müssen Sie bei onStop entsorgen, dann erneut bei onStart / onResume abonnieren, Konfigurationsänderungen vornehmen und eine Reihe anderer Dinge erledigen. Deshalb gibt es so viele Abstürze mit RxJava. LiveData erledigt all das, ist aber nicht so flexibel wie RxJava.
user932178

24

Wie Sie vielleicht im reaktiven Ökosystem wissen, haben wir ein Observable , das Daten ausgibt , und einen Observer , der diese Observable-Emission abonniert (benachrichtigt wird). Nichts Seltsames ist, wie das sogenannte Observer-Muster funktioniert. Ein Observable "schreit" etwas, der Beobachter wird benachrichtigt, dass Observable in einem bestimmten Moment etwas schreit.

Stellen Sie sich LiveDataein Observable vor, mit dem Sie die Beobachter verwalten können, die sich in einem activeZustand befinden. Mit anderen Worten LiveDataist ein einfaches Observable , kümmert sich aber auch um den Lebenszyklus.

Aber sehen wir uns die beiden von Ihnen angeforderten Codefälle an:

A) Live-Daten

B) RXJava

A) Dies ist eine grundlegende Implementierung von LiveData

1) Normalerweise instanziieren Sie LiveData im ViewModel, um die Orientierungsänderung beizubehalten (Sie können schreibgeschützte LiveData oder beschreibbare MutableLiveData verwenden, sodass Sie normalerweise außerhalb der Klasse LiveData verfügbar machen).

2) im OnCreateVerfahren der Hauptaktivität (nicht das Ansichtsmodell) Sie „subscribe“ ein Observer - Objekt (in der Regel eines eine onChanged - Methode)

3) Sie starten die Methode beobachten, um die Verbindung herzustellen

Zuerst die ViewModel(besitzt die Geschäftslogik)

class ViewModel : ViewModel() { //Point 1

    var liveData: MutableLiveData<Int> = MutableLiveData()

}

Und das ist das MainActivity(so dumm wie möglich)

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
        })


        }
    }
}

B) Dies ist die grundlegende Implementierung von RXJava

1) Sie deklarieren ein Observable

2) Sie deklarieren einen Beobachter

3) Sie abonnieren das Observable beim 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);
       }
    });

Insbesondere LiveDatawird mit Lifecycleund häufig mit ViewModel(wie wir gesehen haben) Architekturkomponenten verwendet. In LiveDataKombination mit einem ViewModel können Sie jede Änderung im Observer in Echtzeit auf dem neuesten Stand halten, sodass die Ereignisse bei Bedarf in Echtzeit verwaltet werden. Die Verwendung LiveDatawird dringend empfohlen, um das Konzept des Lebenszyklus und die relativen Objekte LifeCycleOwner / LifeCycle zu kennen . Ich würde Ihnen auch empfehlen , sich Transformationen anzuschauen , wenn Sie sie LiveDatain realen Szenarien implementieren möchten . Hier finden Sie einige Anwendungsfälle aus der großen Commonsware .

Zum Abschluss im GrundeLiveDataist eine vereinfachtesRXJava, eine elegante Art und Weise Änderungen über mehrere Komponenten zu beobachtenohne explizit sogenannte Abhängigkeitsregeln zwischen den Komponentenschaffen, so dass Sie viel einfacherden Code testen und macht es viel besser lesbar. Mit RXJava können Sie die Dinge von LiveData und vieles mehr erledigen. Aufgrund der erweiterten Funktionen von RXJava können Sie sowohl LiveData für einfache Fälle verwenden als auch die gesamte Leistungsfähigkeit von RXJava nutzen und weiterhin Android-Architekturkomponenten als ViewModel verwenden . Dies bedeutet natürlich, dassRXJavadies weitaus komplexer sein kann. Denken Sie nur, dass stattdessen Hunderte von Operatoren vorhanden sind von SwitchMap und Map von LiveData (im Moment).

RXJava Version 2 ist eine Bibliothek, die das objektorientierte Paradigma revolutionierte und eine sogenannte funktionale Methode zur Verwaltung des Programmflusses hinzufügte.


4

LiveData ist eine Teilmenge der Komponenten der Android-Architektur, die vom Android-Team entwickelt wurden.

Bei den Live-Daten und anderen Architekturkomponenten werden Speicherlecks und ähnliche Probleme von Architekturkomponenten behandelt. Da es vom Android-Team entwickelt wurde, ist es das Beste für Android. Sie bieten auch Updates für neue Versionen von Android.

Wenn Sie nur in der Android-App-Entwicklung verwenden möchten, wählen Sie die Android-Architekturkomponenten. Andernfalls verwenden Sie RxJava, wenn Sie andere Java-Apps wie Web-Apps, Desktop-Apps usw. verwenden möchten


Ich habe versucht, Ihre Antwort zu klären. Wenn ich in irgendeiner Weise mit Ihrer ursprünglichen Absicht in Konflikt geraten bin, können Sie diese jederzeit bearbeiten. Wenn Sie dies dennoch tun, versuchen Sie bitte, dies klarer als bei der ersten Überarbeitung zu machen. Der letzte Teil Ihrer Antwort ergab ehrlich gesagt keinen Sinn.
Zoe

2

LiveDataals Dateninhabersache und sonst nichts. Wir können auch sagen, dass LiveData ein Lifecycle-fähiger Verbraucher ist.LiveDataEs wird dringend empfohlen, das Konzept des Lebenszyklus und die relativen Objekte LifeCycleOwner / LifeCycle zu kennen. Sie erhalten Transformations- und Stream-Funktionen für Ihre Geschäftslogik und einen lebenszyklusbewussten Betrieb für Ihre Benutzeroberfläche.

Rx ist ein leistungsstarkes Tool, mit dem Probleme in einem eleganten deklarativen Stil gelöst werden können. Es behandelt geschäftsseitige Optionen oder Service-API-Vorgänge


0

Beim Vergleich von LiveData mit RxJava werden Äpfel mit Obstsalaten verglichen.

Vergleichen Sie LiveData mit ContentObserver und Sie vergleichen Äpfel mit Äpfeln. LiveData ist effektiv ein lebenszyklusbewusster Ersatz für ContentObserver.

Beim Vergleich von RxJava mit AsyncTask oder einem anderen Threading-Tool werden Obstsalate mit Orangen verglichen, da RxJava nicht nur beim Threading hilft.


0
  • LiveData entspricht teilweise Rx Subject oder SharedRxObservable

  • LiveData verwaltet den Lebenszyklus des Abonnements, das Rx Subject-Abonnement sollte jedoch manuell erstellt und entsorgt werden

  • LiveData hat keinen Beendigungsstatus, aber Rx Subject hat OnError und OnCompleted

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.