J'utilise RxJava dans mon Android et je souhaite charger des données à partir de la base de données.
De cette façon, je crée un nouvel observable en utilisant Observable.create()
qui retourne une liste de EventLog
public Observable<List<EventLog>> loadEventLogs() {
return Observable.create(new Observable.OnSubscribe<List<EventLog>>() {
@Override
public void call(Subscriber<? super List<EventLog>> subscriber) {
List<DBEventLog> logs = new Select().from(DBEventLog.class).execute();
List<EventLog> eventLogs = new ArrayList<>(logs.size());
for (int i = 0; i < logs.size(); i++) {
eventLogs.add(new EventLog(logs.get(i)));
}
subscriber.onNext(eventLogs);
}
});
}
Bien que cela fonctionne correctement, j'ai lu que l'utilisation de Observable.create()
n'est pas en fait une meilleure pratique pour Rx Java (voir ici ).
J'ai donc changé cette méthode de cette façon.
public Observable<List<EventLog>> loadEventLogs() {
return Observable.fromCallable(new Func0<List<EventLog>>() {
@Override
public List<EventLog> call() {
List<DBEventLog> logs = new Select().from(DBEventLog.class).execute();
List<EventLog> eventLogs = new ArrayList<>(logs.size());
for (int i = 0; i < logs.size(); i++) {
eventLogs.add(new EventLog(logs.get(i)));
}
return eventLogs;
}
});
}
Est-ce une meilleure approche en utilisant Rx Java? Pourquoi? Quelle est réellement la différence entre les deux méthodes?
De plus, puisque la base de données charge une liste d'éléments, est-il judicieux d'émettre la liste entière à la fois? Ou dois-je émettre un élément à la fois?
Les deux méthodes peuvent sembler similaires et se comporter de la même façon, mais fromCallable
gère les difficultés de contre-pression pour vous, contrairement à la version create
. La gestion de la contre-pression dans une implémentation de OnSubscribe
va de la simple à la déconcertante; cependant, s'il est omis, vous pouvez obtenir MissingBackpressureException
s le long des frontières asynchrones (telles que observeOn
) ou même sur les frontières de continuation (telles que concat
).
RxJava essaie d'offrir une prise en charge adéquate de la contre-pression pour autant d'usines et d'opérateurs que possible, cependant, il y a pas mal d'usines et d'opérateurs qui ne peuvent pas la prendre en charge.
Le deuxième problème avec l'implémentation manuelle de OnSubscribe
est le manque de support d'annulation, surtout si vous générez beaucoup d'appels onNext
. Beaucoup d'entre eux peuvent être remplacés par des méthodes d'usine standard (telles que from
) ou des classes d'assistance (telles que SyncOnSubscribe
) qui traitent de toute la complexité pour vous.
Vous pouvez trouver de nombreuses introductions et exemples qui utilisent (toujours) create
pour deux raisons.
create
proportionnellement au lieu de parler des méthodes d'usine standard et de montrer comment certaines tâches courantes (comme la vôtre) peuvent être accomplies en toute sécurité.Pour la deuxième question, à savoir si l'on doit créer une liste ou une séquence de valeurs, cela dépend de votre source. Si votre source prend en charge une sorte d'itération ou de streaming d'éléments de données individuels (tels que JDBC), vous pouvez simplement vous y connecter et émettre un par un (voir SyncOnSubscribe
). S'il ne le prend pas en charge ou si vous en avez besoin sous forme de liste, conservez-le tel quel. Vous pouvez toujours convertir entre les deux formulaires via toList
et flatMapIterable
si nécessaire.
Comme il est expliqué dans la réponse vous avez lié, avec Observable.create
vous devrez peut-être enfreindre les exigences avancées de RxJava.
Par exemple, vous devrez implémenter backpressure , ou comment vous désinscrire.
Dans votre cas, vous souhaitez émettre un élément, sans avoir à faire face à la contre-pression ou à l'abonnement. Alors Observable.fromCallable
est un bon appel. RxJava s'occupera du reste.