Pour le simple travail en réseau, les avantages de RxJava par rapport à Callback sont très limités. L'exemple simple de getUserPhoto :
RxJava :
api.getUserPhoto(photoId)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Photo>() {
@Override
public void call(Photo photo) {
// do some stuff with your photo
}
});
Rappel :
api.getUserPhoto(photoId, new Callback<Photo>() {
@Override
public void onSuccess(Photo photo, Response response) {
}
});
La variante RxJava n'est pas beaucoup mieux que la variante Callback. Pour l'instant, ignorons la gestion des erreurs. Prenons une liste de photos :
RxJava :
api.getUserPhotos(userId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMap(new Func1<List<Photo>, Observable<Photo>>() {
@Override
public Observable<Photo> call(List<Photo> photos) {
return Observable.from(photos);
}
})
.filter(new Func1<Photo, Boolean>() {
@Override
public Boolean call(Photo photo) {
return photo.isPNG();
}
})
.subscribe(
new Action1<Photo>() {
@Override
public void call(Photo photo) {
list.add(photo)
}
});
Rappel :
api.getUserPhotos(userId, new Callback<List<Photo>>() {
@Override
public void onSuccess(List<Photo> photos, Response response) {
List<Photo> filteredPhotos = new ArrayList<Photo>();
for(Photo photo: photos) {
if(photo.isPNG()) {
filteredList.add(photo);
}
}
}
});
Maintenant, la variante RxJava n'est toujours pas plus petite, bien qu'avec les Lambdas, elle se rapprocherait de la variante Callback. De plus, si vous avez accès au flux JSON, il serait un peu bizarre de récupérer toutes les photos alors que vous n'affichez que les PNG. Il suffit d'ajuster le flux pour qu'il n'affiche que les PNG.
Première conclusion
Cela ne réduit pas votre base de code lorsque vous chargez un simple JSON que vous avez préparé pour être dans le bon format.
Maintenant, rendons les choses un peu plus intéressantes. Disons que vous ne voulez pas seulement récupérer la photo de l'utilisateur, mais que vous avez un clone d'Instagram, et que vous voulez récupérer 2 JSONs : 1. getUserDetails() 2. getUserPhotos()
Vous voulez charger ces deux JSON en parallèle, et lorsque les deux sont chargés, la page doit s'afficher. La variante callback va devenir un peu plus difficile : vous devez créer 2 callbacks, stocker les données dans l'activité, et si toutes les données sont chargées, afficher la page :
Rappel :
api.getUserDetails(userId, new Callback<UserDetails>() {
@Override
public void onSuccess(UserDetails details, Response response) {
this.details = details;
if(this.photos != null) {
displayPage();
}
}
});
api.getUserPhotos(userId, new Callback<List<Photo>>() {
@Override
public void onSuccess(List<Photo> photos, Response response) {
this.photos = photos;
if(this.details != null) {
displayPage();
}
}
});
RxJava :
private class Combined {
UserDetails details;
List<Photo> photos;
}
Observable.zip(api.getUserDetails(userId), api.getUserPhotos(userId), new Func2<UserDetails, List<Photo>, Combined>() {
@Override
public Combined call(UserDetails details, List<Photo> photos) {
Combined r = new Combined();
r.details = details;
r.photos = photos;
return r;
}
}).subscribe(new Action1<Combined>() {
@Override
public void call(Combined combined) {
}
});
Nous arrivons à quelque chose ! Le code de RxJava est maintenant aussi gros que l'option callback. Le code de RxJava est plus robuste ; Pensez à ce qui se passerait si nous avions besoin de charger un troisième JSON (comme les dernières vidéos) ? La RxJava n'aurait besoin que d'un ajustement minuscule, alors que la variante Callback doit être ajustée à plusieurs endroits (à chaque callback, nous devons vérifier si toutes les données sont récupérées).
Un autre exemple : nous voulons créer un champ de saisie automatique qui charge des données en utilisant Retrofit. Nous ne voulons pas faire un webcall à chaque fois qu'un EditText a un TextChangedEvent. Lorsque l'on tape rapidement, seul le dernier élément doit déclencher l'appel. Sur RxJava, nous pouvons utiliser l'opérateur debounce :
inputObservable.debounce(1, TimeUnit.SECONDS).subscribe(new Action1<String>() {
@Override
public void call(String s) {
// use Retrofit to create autocompletedata
}
});
Je ne vais pas créer la variante Callback mais vous comprendrez que cela représente beaucoup plus de travail.
Conclusion : RxJava est exceptionnellement bon lorsque les données sont envoyées sous forme de flux. L'Observable Retrofit pousse tous les éléments du flux en même temps. Ce n'est pas particulièrement utile en soi par rapport au Callback. Mais quand il y a plusieurs éléments poussés sur le flux et à des moments différents, et que vous devez faire des choses liées au timing, RxJava rend le code beaucoup plus facile à maintenir.
0 votes
Pouvez-vous mettre à jour votre lien vers le fichier dont vous parlez dans U2020
0 votes
Il fonctionne toujours...
6 votes
Mec, j'ai eu exactement les mêmes pensées quand j'ai lu que RxJava était la nouvelle chose. J'ai lu un exemple de rétrofit (parce que je suis extrêmement familier avec ça) d'une requête simple et c'était dix ou quinze lignes de code et ma première réaction a été : tu dois te moquer de moi =/ . Je n'arrive pas non plus à comprendre comment cela remplace un bus d'événements, car le bus d'événements vous découple de l'observable et rxjava réintroduit le couplage, sauf erreur de ma part.