Quand utiliser RxJava sous Android et quand utiliser LiveData à partir des composants architecturaux Android?

197

Je ne comprends pas la raison d'utiliser RxJava dans Android et LiveData à partir de composants architecturaux Android.Il serait vraiment utile que les cas d'utilisation et les différences entre les deux soient expliqués avec un exemple d'exemple sous forme de code qui explique les différences entre les deux.

rahul66
la source
7
Avez-vous encore trouvé une bonne raison? Je me demande la même chose ...
IgorGanapolsky

Réponses:

119

Android LiveData est une variante du modèle d'observateur d'origine, avec l'ajout de transitions actives / inactives. En tant que tel, sa portée est très restrictive.

À l'aide de l'exemple décrit dans Android LiveData , une classe est créée pour surveiller les données de localisation, puis s'inscrire et se désinscrire en fonction de l'état de l'application.

RxJava fournit des opérateurs beaucoup plus généralisés. Supposons que cette observable fournira des données de localisation:

Observable<LocationData> locationObservable;

L'implémentation de l'observable peut être construite en utilisant Observable.create()pour mapper les opérations de rappel. Lorsque l'observable est abonné, le rappel est enregistré, et lorsqu'il est désabonné, le rappel n'est pas enregistré. L'implémentation ressemble beaucoup au code fourni dans l'exemple.

Supposons également que vous ayez une observable qui émet true lorsque l'application est active:

Observable<Boolean> isActive;

Ensuite, vous pouvez fournir toutes les fonctionnalités de LiveData comme suit

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

L' switchMap()opérateur fournira soit l'emplacement actuel sous forme de flux, soit rien si l'application n'est pas active. Une fois que vous avez l' liveLocationobservable, vous pouvez en faire beaucoup en utilisant les opérateurs RxJava. Mon exemple préféré est:

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

Cela n'effectuera l'action que lorsque l'emplacement a changé et que l'emplacement est intéressant. Vous pouvez créer des opérations similaires qui combinent des opérateurs de temps pour déterminer la vitesse. Plus important encore, vous pouvez fournir un contrôle détaillé pour savoir si les opérations se produisent dans le thread principal, ou un thread d'arrière-plan ou plusieurs threads, à l'aide des opérateurs RxJava.

L'intérêt de RxJava est qu'il combine le contrôle et la synchronisation dans un seul univers, en utilisant les opérations fournies par la bibliothèque, ou même les opérations personnalisées que vous fournissez.

LiveData n'aborde qu'une petite partie de cet univers, l'équivalent de la création du liveLocation.

Bob Dalgleish
la source
2
Merci, les documents LiveData ne semblent plus référencer un échantillon d'emplacement. Il y a plus de points intéressants (avec un exemple de localisation) ici: androidkt.com/livedata
Daniel Wilson
5
@DanielWilson le lien n'est plus disponible.
Tura
1
Mec, je ne me souviens pas que wtf était sur ce lien: DI comme l'exemple de code de Mark Allison pour des données en direct: blog.stylingandroid.com/architecture-components-livedata
Daniel Wilson
4
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. Mais n'est pas conscient du cycle de vie LiveData. Si nous devions utiliser Rx, n'aurions-nous pas à gérer les changements du cycle de vie?
Sparker0i
@ Sparker0i a obtenu un point ici. RxJava n'est pas conscient du cycle de vie. nous devons gérer manuellement. où comme dans LiveData, il est déjà pris en charge le cycle de vie.
Aks4125
126

En ce qui concerne la question initiale, RxJava et LiveData se complètent très bien.

LiveDatabrille sur la couche ViewModel, avec son intégration étroite avec les cycles de vie Android et ViewModel. RxJavafournit plus de capacités dans les transformations (comme mentionné par @Bob Dalgleish).

Actuellement, nous utilisons RxJavadans les couches de source de données et de référentiel, et il est transformé en LiveData(utilisation LiveDataReactiveStreams) dans ViewModels (avant d'exposer les données à des activités / fragments) - assez satisfaits de cette approche.

kzotin
la source
9
Si nous vous avons bien compris, LiveData n'est utile que pour les implémentations spécifiques à l'interface utilisateur Android. Si nous construisons simplement une application générique avec une architecture propre et partageons cette architecture avec d'autres plates-formes, alors RxJava convient-il mieux que LiveData?
IgorGanapolsky
@IgorGanapolsky quel langage / quels frameworks utilisez-vous pour une application générique?
kzotin
3
pouvez-vous suggérer un exemple fonctionnel de LiveDataReactiveStreams dans votre réponse?
Pawan
2
@kzotin vous n'en avez pas besoin observeOn, le LiveDataReactiveStreamsfait quand même en appelant LiveData.postValue(). Et il n'y a aucune garantie que votre subscribeOnvolonté aura un effet en général.
arekolek
1
J'ai trouvé cet excellent article sur le grand ranch de nerd où RxJava rencontre LiveData
Mohammad Reza Khahani
91

Il existe de nombreuses différences entre LiveData et RxJava:

  1. LiveData n'est pas un STREAM alors que dans RxJava tout (littéralement tout) est un STREAM .
  2. LiveData est une classe de détenteurs de données observables. Contrairement à un observable ordinaire, LiveData est sensible au cycle de vie, ce qui signifie qu'il respecte le cycle de vie des autres composants de l'application, tels que les activités, les fragments ou les services. Cette prise de conscience garantit que LiveData met à jour uniquement les observateurs de composants d'application qui sont dans un état de cycle de vie actif.
  3. LiveData est synchrone , vous ne pouvez donc pas exécuter un morceau de code (appel réseau, manipulation de base de données, etc.) de manière asynchrone en utilisant uniquement LiveData comme vous le faites avec RxJava.
  4. Le mieux que vous puissiez faire pour exploiter au maximum ce duo est d'utiliser RxJava pour votre logique métier (appel réseau, manipulation de données, etc., tout ce qui se passe dans et au-delà du référentiel ) et d'utiliser LiveData pour votre couche de présentation. Ainsi, vous bénéficiez de capacités de transformation et de flux pour votre logique métier et une opération tenant compte du cycle de vie de votre interface utilisateur.
  5. LiveData et RxJava se complètent s'ils sont utilisés ensemble. Ce que je veux dire, c'est tout faire avec RxJava et à la fin, lorsque vous souhaitez mettre à jour l'interface utilisateur, faites quelque chose comme le code ci-dessous pour changer votre Observable en LiveData. Ainsi, votre View (UI) observe les LiveData dans ViewModel où votre LiveData n'est rien d'autre que MutableLiveData non mutable (ou MutableLiveData est LiveData mutable).
  6. La question ici est donc: pourquoi devriez-vous même utiliser LiveData en premier lieu? Comme vous pouvez le voir ci-dessous dans le code, vous stockez votre réponse de RxJava à MutableLiveData (ou LiveData) et votre LiveData est sensible au cycle de vie, donc d'une certaine manière, vos données sont sensibles au cycle de vie. Maintenant, imaginez la possibilité lorsque vos données elles-mêmes savent quand et quand ne pas mettre à jour l'interface utilisateur.
  7. LiveData n'a pas d'historique (juste l'état actuel). Par conséquent, vous ne devez pas utiliser LiveData pour une application de chat.
  8. Lorsque vous utilisez LiveData avec RxJava, vous n'avez pas besoin de trucs comme MediatorLiveData , SwitchMap, etc. Ce sont des outils de contrôle de flux et RxJava est souvent meilleur dans ce domaine.
  9. Voyez LiveData comme une chose de détenteur de données et rien d'autre. Nous pouvons également dire que LiveData est un consommateur sensible au cycle de vie.

    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();
         }
    }
Abhishek Kumar
la source
6
Voyez LiveData comme une chose de détenteur de données et rien d'autre. ==> OUI
Lou Morda
4
Bel exemple. Vous avez oublié de déclarer le jetable et ce serait bien de le vider onCleared.
Snicolas
Pourriez-vous s'il vous plaît expliquer en quoi Liveata est synchrone? Pour autant que je sache, nous pouvons envoyer un objet Livedata à un autre thread, puis ce thread peut postvaluer quel observateur peut écouter dans MainThread.
Hitesh Bisht
Si vous relisez ce que j'ai écrit, cela signifie que vous ne pouvez pas travailler sur un autre thread juste (OUI, j'ai utilisé "juste" même là) en utilisant LiveData comme vous pouvez le faire en utilisant RxJava
Abhishek Kumar
1
J'envisage d'utiliser Rx pour les appels réseau comme un anti-pattern. La plupart des choses ne sont pas des flux. Je sais. C'est un choc. Mais ils ne le sont pas. Les gens qui construisent leur vie autour de Rx disent qu'ils le sont, mais ils ne le sont vraiment pas. Sauf si vous utilisez un abonnement, un appel réseau a un résultat unique. Et un flux avec un seul résultat est tout simplement stupide. C'est comme traiter tout comme un clou parce que vous avez un marteau.
funct7
29

En fait, LiveData n'est pas un outil essentiellement différent RxJava, alors pourquoi at - il été introduit en tant que composante de l' architecture où RxJavaaurait pu facile à gérer le cycle de vie en stockant tous les abonnements à des observables dans un CompositeDispoable objet, puis les disposer dans onDestroy() des Activity ou onDestroyView() de l' Fragment utilisation d' un seul ligne de code?

J'ai répondu entièrement à cette question en créant une application de recherche de films une fois en utilisant RxJava, puis en utilisant LiveData ici .

Mais en bref, oui, c'est possible, mais il faudrait d'abord remplacer les méthodes de cycle de vie pertinentes en plus d'avoir les connaissances de base sur le cycle de vie. Cela n'a peut-être toujours pas de sens pour certains, mais le fait est que selon l'une des sessions Jetpack de Google I / O 2018, de nombreux développeurs trouvent la gestion du cycle de vie complexe. Les erreurs de plantage résultant de la non-gestion de la dépendance au cycle de vie peuvent être un autre signe que certains développeurs, même s'ils connaissent le cycle de vie, oublient de s'en occuper dans chaque activité / fragment qu'ils utilisent dans leur application. Dans les grandes applications, cela pourrait devenir un problème, malgré l'effet négatif que cela pourrait avoir sur la productivité.

L'essentiel est qu'en introduisant LiveData, un plus grand nombre de développeurs devraient adopter MVVM sans même avoir à comprendre la gestion du cycle de vie, les fuites de mémoire et les pannes. Même si je n'ai aucun doute que ce LiveDatan'est pas comparable RxJavaen termes de capacités et de puissance qu'elle donne aux développeurs, la programmation réactive et RxJavac'est un concept et un outil difficile à comprendre pour beaucoup. D'un autre côté, je ne pense pas que ce LiveDatasoit censé remplacer RxJava- ce n'est tout simplement pas possible - mais un outil très simple pour gérer un problème très répandu et controversé rencontré par de nombreux développeurs.

** MISE À JOUR ** J'ai ajouté un nouvel article ici où j'ai expliqué comment une mauvaise utilisation de LiveData peut conduire à des résultats inattendus. RxJava peut venir à la rescousse dans ces situations


Ali Nem
la source
2
"pourquoi a-t-il été introduit alors que RxJava aurait pu facilement gérer le cycle de vie en stockant tous les abonnements dans un CompositeDispoable puis en les éliminant dans onDestroy () de l'activité" - LiveDatadisposerait en onStopfait
arekolek
@arekolek d'après ce que je comprends: même pour gérer le CompositeDispoable, nous avons écrasé les méthodes du cycle de vie. Mais dans les données en direct, tout sera inclus dans une seule ligne de code. Nous économisons donc au minimum 20 lignes de code.
Suresh
Nous pouvons définir un baseFragment et définir la méthode Disposable [] subscriptions () à remplacer par tous les fragments dérivés, appeler cette méthode dans onCreateView et ajouter la valeur de retour dans un CompositeDisposable, disposer cela dans onDestroyView, plus d'oubli.
android2013
Il ne s'agit pas seulement de se débarrasser. En utilisant RxJava, vous devez disposer sur onStop, puis vous abonner à nouveau dans onStart / onResume, gérer les modifications de configuration et faire un tas d'autres choses. C'est pourquoi il y a tant de plantages avec RxJava. LiveData gère tout cela, mais n'est pas aussi flexible que RxJava.
user932178
26

Comme vous le savez peut-être dans l'écosystème réactif, nous avons un observable qui émet des données et un observateur qui s'abonne (se fait notifier) ​​de cette émission observable, rien d'étrange n'est comment fonctionne le soi-disant modèle d'observateur. Un observable «crie» quelque chose, l'observateur est notifié que l'observable crie quelque chose à un moment donné.

Pensez à LiveDataun observable qui vous permet de gérer les observateurs qui sont dans un activeétat. En d'autres termes, LiveDatac'est un simple observable mais prend également en charge le cycle de vie.

Mais voyons les deux cas de code que vous demandez:

A) Données en direct

B) RXJava

A) Ceci est une implémentation de base de LiveData

1) vous instanciez généralement LiveData dans le ViewModel pour maintenir le changement d'orientation (vous pouvez avoir LiveData en lecture seule, ou MutableLiveData en écriture, donc vous exposez généralement en dehors de la classe LiveData)

2) dans la OnCreateméthode de l' activité principale (pas le ViewModel), vous «abonnez» un objet Observer (généralement une méthode onChanged)

3) vous lancez la méthode observer pour établir le lien

D'abord le ViewModel(possède la logique métier)

class ViewModel : ViewModel() { //Point 1

    var liveData: MutableLiveData<Int> = MutableLiveData()

}

Et c'est le MainActivity(aussi stupide que possible)

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) Ceci est l'implémentation de base de RXJava

1) vous déclarez un observable

2) vous déclarez un observateur

3) vous souscrivez à l'Observable avec l'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);
       }
    });

En particulier, il LiveDataest utilisé avec Lifecycleet souvent avec ViewModel(comme nous l'avons vu) des composants d'architecture. En fait, quand LiveDataest combiné avec un ViewModel vous permet de garder à jour en temps réel chaque changement dans l'Observer, de sorte que les événements sont gérés en temps réel là où c'est nécessaire. L'utilisation LiveDataest fortement recommandée pour connaître le concept de cycle de vie et les objets relatifs LifeCycleOwner / LifeCycle , aussi je vous suggère de jeter un oeil à Transformations , si vous souhaitez implémenter LiveDatadans des scénarios de la vie réelle. Vous trouverez ici quelques cas d'utilisation du grand logiciel commun .

Pour conclure essentiellementLiveDataest unesimplifiéeRXJava,une manière élégante d'observerchangements sur plusieurs composants sans créerrègles de dépendance explicites soidisant entre les composants,sorte que vous pouvez tester beaucoup plus facile le code etrendre beaucoup plus facilelire. RXJava, vous permet de faire les choses de LiveData et bien plus encore. En raison des fonctionnalités étendues de RXJava, vous pouvez à la fois utiliser LiveData pour des cas simples ou exploiter toute la puissance de RXJava continuer à utiliser des composants d'architecture Android comme ViewModel , bien sûr, cela signifie que celaRXJavapeut être beaucoup plus complexe, pensez simplement à des centaines d'opérateurs à la place de SwitchMap et Map of LiveData (pour le moment).

RXJava version 2 est une bibliothèque qui a révolutionné le paradigme orienté objet, en ajoutant une méthode dite fonctionnelle pour gérer le flux du programme.

trocchietto
la source
5

LiveData est un sous-ensemble des composants de l'architecture Android qui est développé par l'équipe Android.

Avec les données en direct et d'autres composants d'architecture, les fuites de mémoire et d'autres problèmes similaires sont gérés par les composants d'architecture. Puisqu'il est développé par l'équipe Android, c'est le meilleur pour Android. Ils fournissent également des mises à jour qui gèrent les nouvelles versions d'Android.

Si vous ne souhaitez utiliser que dans le développement d'applications Android, optez pour les composants d'architecture Android. Sinon, si vous souhaitez utiliser une autre application Java, comme une application Web, des applications de bureau, etc., utilisez RxJava

SIVAKUMAR.J
la source
J'ai essayé de clarifier votre réponse. Si je suis en conflit avec votre intention initiale, n'hésitez pas à modifier. Si c'est le cas, essayez de le rendre plus clair que la révision initiale. La dernière partie de votre réponse n'avait honnêtement aucun sens.
Zoe
2

LiveDatacomme une chose de détenteur de données et rien d'autre. Nous pouvons également dire que LiveData est un consommateur conscient du cycle de vie. LiveDataIl est fortement recommandé de connaître le concept de cycle de vie et les objets relatifs LifeCycleOwner / LifeCycle, vous obtenez des capacités de transformation et de flux pour votre logique métier et une opération tenant compte du cycle de vie de votre interface utilisateur.

Rx est un outil puissant qui permet de résoudre des problèmes dans un style déclaratif élégant. Il gère les options côté entreprise ou les opérations de service Api

Attif
la source
1

Comparer LiveData à RxJava, c'est comparer des pommes avec des salades de fruits.

Comparez LiveData à ContentObserver et vous comparez des pommes avec des pommes. LiveData est en fait un remplacement sensible au cycle de vie de ContentObserver.

Comparer RxJava à AsyncTask ou à tout autre outil de filetage consiste à comparer des salades de fruits à des oranges, car RxJava aide avec plus que le simple filetage.

Straya
la source
1
  • LiveData est partiellement égal à Rx Subject ou SharedRxObservable

  • LiveData gère le cycle de vie de l'abonnement, mais l'abonnement Rx Subject doit être créé et supprimé manuellement

  • LiveData n'a pas d'état de terminaison mais Rx Subject a OnError et OnCompleted

Sergey M
la source