Per semplici elementi di rete, i vantaggi di RxJava rispetto a Callback sono molto limitati. Il semplice esempio getUserPhoto:
RxJava:
api.getUserPhoto(photoId)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Photo>() {
@Override
public void call(Photo photo) {
// do some stuff with your photo
}
});
Richiama:
api.getUserPhoto(photoId, new Callback<Photo>() {
@Override
public void onSuccess(Photo photo, Response response) {
}
});
La variante RxJava non è molto migliore della variante Callback. Per ora, ignoriamo la gestione degli errori. Facciamo un elenco di foto:
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)
}
});
Richiama:
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);
}
}
}
});
Ora, la variante RxJava non è ancora più piccola, anche se con Lambdas sarebbe più vicina alla variante Callback. Inoltre, se hai accesso al feed JSON, sarebbe un po 'strano recuperare tutte le foto quando visualizzi solo i PNG. Basta regolare il feed in modo da visualizzare solo i PNG.
Prima conclusione
Non rende più piccola la tua base di codice quando carichi un semplice JSON che hai preparato per essere nel formato giusto.
Ora, rendiamo le cose un po 'più interessanti. Diciamo che non vuoi solo recuperare l'utentePhoto, ma hai un clone di Instagram e vuoi recuperare 2 JSON: 1. getUserDetails () 2. getUserPhotos ()
Volete caricare questi due JSON in parallelo e quando entrambi vengono caricati, la pagina dovrebbe essere visualizzata. La variante di callback diventerà un po 'più difficile: devi creare 2 callback, archiviare i dati nell'attività e, se tutti i dati sono caricati, visualizzare la pagina:
Richiama:
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) {
}
});
Stiamo arrivando da qualche parte! Il codice di RxJava è ora grande quanto l'opzione di callback. Il codice RxJava è più robusto; Pensa a cosa accadrebbe se avessimo bisogno di un terzo JSON da caricare (come gli ultimi video)? RxJava avrebbe solo bisogno di una piccola modifica, mentre la variante Callback deve essere regolata in più posizioni (su ogni callback è necessario verificare se tutti i dati vengono recuperati).
Un altro esempio; vogliamo creare un campo di completamento automatico, che carica i dati usando Retrofit. Non vogliamo fare una webcall ogni volta che un EditText ha un TextChangedEvent. Quando si digita velocemente, solo l'ultimo elemento dovrebbe attivare la chiamata. Su RxJava possiamo usare l'operatore debounce:
inputObservable.debounce(1, TimeUnit.SECONDS).subscribe(new Action1<String>() {
@Override
public void call(String s) {
// use Retrofit to create autocompletedata
}
});
Non creerò la variante di Callback ma capirai che questo è molto più lavoro.
Conclusione: RxJava è eccezionalmente buono quando i dati vengono inviati come flusso. Retrofit Observable spinge tutti gli elementi nello stream contemporaneamente. Questo non è particolarmente utile in sé rispetto a Callback. Ma quando ci sono più elementi spinti sullo stream e tempi diversi, e devi fare cose relative al timing, RxJava rende il codice molto più gestibile.