web-dev-qa-db-fra.com

Convertissez les observables RxJava en données en temps réel avec les fonctions d'extension Kotlin

J'ai utilisé beaucoup de RxJava Observables converti en LiveData dans mon code en utilisant la bibliothèque LiveDataReactiveStreams.fromPublisher(). J'ai donc pensé à ajouter une fonction d'extension à RxJava Observable pour les convertir facilement en LiveData.

Ce sont mes fonctions d'extension:

fun <T> Flowable<T>.toLiveData() :  LiveData<T> {
    return LiveDataReactiveStreams.fromPublisher(this)
}

fun <T> Observable<T>.toLiveData(backPressureStrategy: BackpressureStrategy) :  LiveData<T> {
    return LiveDataReactiveStreams.fromPublisher(this.toFlowable(backPressureStrategy))
}

fun <T> Single<T>.toLiveData() :  LiveData<T> {
    return LiveDataReactiveStreams.fromPublisher(this.toFlowable())
}

fun <T> Maybe<T>.toLiveData() :  LiveData<T> {
    return LiveDataReactiveStreams.fromPublisher(this.toFlowable())
}

fun <T> Completable.toLiveData() :  LiveData<T> {
    return LiveDataReactiveStreams.fromPublisher(this.toFlowable())
}

Mes questions sont:

  1. Est-ce une bonne idée?
  2. Existe-t-il une meilleure façon de le faire?
  3. Ces fonctions d'extension pourraient-elles être meilleures?

P.S.

Je suis nouveau à Kotlin et je pose donc ces questions. Tout ce qui serait utile serait apprécié. Merci beaucoup.

13

Je pense que c'est une très bonne idée. Un exemple d'avantage de LiveData est la possibilité de l'utiliser directement dans vos présentations de liaison de données. Disons que dans votre modèle de vue, vous avez:

val user: LiveData<User>

data class User(val firstName: String, val lastName: String)

dans votre mise en page, vous pouvez lier directement les propriétés de la User:

Android:text="${viewModel.user.firstName}"

Vous ne pouvez pas utiliser des flux réactifs dans la liaison de données comme ceci. Si user était Flowable<User>, référencer ${viewModel.user.firstName} ne fonctionnerait pas.

De plus, la liaison de données gérera le cycle de vie pour vous (observer les modifications uniquement en état actif et mettre à jour la vue lorsque des modifications se produisent) si votre activité ou votre fragment appelle ViewDataBinding.setLifecycleOwner(LifecycleOwner) :

binding.setLifecycleOwner(this)

Celui qui convertit Completable en LiveData<T> n’a pas vraiment de sens, car il n’informera jamais l’observateur de quoi que ce soit, je voudrais donc simplement m'en débarrasser.

Il y a quelques considérations à prendre en compte lors de la conversion de flux réactifs en données en direct (comme lorsque je voulais reprendre un compte à rebours après la rotation ), mais je ne pense pas qu'ils soient liés aux fonctions d'extension que vous avez présentées. faire leur travail. Il convient de garder à l'esprit que lorsque le propriétaire du cycle de vie passe de l'état actif à l'état inactif, PublisherLiveData annule l'abonnement au flux et lorsque l'état passe à l'état actif, il crée un nouvel abonnement, ce qui signifie un redémarrage. le flux dans de nombreux cas (je suppose que c'est si le flux est "froid"), alors que vous voulez probablement reprendre le flux à l'endroit où il se trouvait après la rotation ou d'autres changements de configuration. Par contre, si le flux était "chaud", les émissions sont ignorées pendant l'état inactif. Je pense que ce problème doit être résolu même si vous utilisiez directement les flux réactifs et si vous gériez le cycle de vie manuellement. Mais le problème est que la simple conversion de flux réactifs en LiveData ne suffit pas pour résoudre ce problème.

Il est bon de documenter ces méthodes car elles ne gèrent pas l'état d'erreur, qui doit être traité en amont. Cela pourrait également être l’une des améliorations apportées à ces fonctions: transformer le flux en premier pour gérer les erreurs (en tant que paramètre lambda avec une valeur par défaut, par exemple). Une autre possibilité serait d'utiliser Result (expérimental pour le moment), ou quelque chose de similaire pour encapsuler le succès ou l'erreur.


Après coup, en ce qui concerne cette partie que j'ai écrite ci-dessus:

Il existe certaines considérations lors de la conversion de flux réactifs en données actives, mais je ne pense pas qu'elles soient liées aux fonctions d'extension que vous avez présentées.

Je pense toujours que cela reste vrai en général, mais je ne suis pas sûr que vous souhaitiez réellement utiliser Single.toLiveData() et Maybe.toLiveData() dans la plupart des cas. Puisque Maybe et Single modélisent des opérations uniques, il peut être préférable de ne pas l'annuler s'il n'y a pas d'observateur actif et de devoir le redémarrer une fois qu'il y a de nouveaux observateurs actifs. Il peut être utile d’afficher dans une variable MutableLiveData et de disposer de la variable SingleMaybe DANS onCleared (JE NE SUIS PAS S&UCIRC;R QUE CELA PUISSE &ECIRC;TRE ENCAPSUL&EACUTE; DANS UNE FONCTION D&RSQUO;EXTENSION). ILS PEUVENT ENCORE AVOIR UNE UTILIT&EACUTE; QUE JE NE VOIS TOUT SIMPLEMENT PAS POUR LE MOMENT.

EN PASSANT, VOTRE Flowable.toLiveData() EST D&EACUTE;J&AGRAVE; DANS L'ARTEFACT _/androidx.lifecycle:lifecycle-reactivestreams-ktx .

Cela laisse la Observable.toLiveData(), qui, à mon avis, devrait être tout aussi utile que celle de Flowable.

7
arekolek

Votre solution est satisfaisante si vous souhaitez utiliser LiveData et Rx ensemble.

Si vous souhaitez simplement disposer automatiquement de votre abonnement, vous pouvez le mettre en œuvre sur Disposable comme suit:

private class LifecycleDisposable(obj: Disposable) :
        DefaultLifecycleObserver, Disposable by obj {
    override fun onStop(owner: LifecycleOwner) {
        if (!isDisposed) {
            dispose()
        }
    }
}

fun Disposable.attachToLifecycle(owner: LifecycleOwner) {
    owner.lifecycle.addObserver(LifecycleDisposable(this))
}

et l'appelle comme

Observable.just(1, 2, 3).subscribe().attachToLifecycle(this)

this fait référence à n'importe quel LifecycleOwner.

2
harry248

Ces fonctions peuvent être un peu plus courtes, mais ce n’est pas une bonne idée du tout. Rx donne beaucoup plus de possibilités que les auditeurs LiveData

0