Für einfache Netzwerkaufgaben sind die Vorteile von RxJava gegenüber Callback sehr begrenzt. Das einfache getUserPhoto-Beispiel:
RxJava:
api.getUserPhoto(photoId)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Photo>() {
@Override
public void call(Photo photo) {
// do some stuff with your photo
}
});
Zurückrufen:
api.getUserPhoto(photoId, new Callback<Photo>() {
@Override
public void onSuccess(Photo photo, Response response) {
}
});
Die RxJava-Variante ist nicht viel besser als die Callback-Variante. Lassen Sie uns vorerst die Fehlerbehandlung ignorieren. Machen wir eine Liste mit Fotos:
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)
}
});
Zurückrufen:
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);
}
}
}
});
Jetzt ist die RxJava-Variante immer noch nicht kleiner, obwohl sie mit Lambdas der Callback-Variante näher kommen würde. Wenn Sie Zugriff auf den JSON-Feed haben, ist es außerdem seltsam, alle Fotos abzurufen, wenn Sie nur die PNGs anzeigen. Passen Sie einfach den Feed an, um nur PNGs anzuzeigen.
Erste Schlussfolgerung
Dadurch wird Ihre Codebasis nicht kleiner, wenn Sie einen einfachen JSON laden, den Sie für das richtige Format vorbereitet haben.
Lassen Sie uns die Dinge jetzt etwas interessanter machen. Angenommen, Sie möchten nicht nur das userPhoto abrufen, sondern haben auch einen Instagram-Klon und möchten 2 JSONs abrufen: 1. getUserDetails () 2. getUserPhotos ()
Sie möchten diese beiden JSONs parallel laden. Wenn beide geladen sind, sollte die Seite angezeigt werden. Die Rückrufvariante wird etwas schwieriger: Sie müssen 2 Rückrufe erstellen, die Daten in der Aktivität speichern und, wenn alle Daten geladen sind, die Seite anzeigen:
Zurückrufen:
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) {
}
});
Wir kommen irgendwohin! Der Code von RxJava ist jetzt so groß wie die Rückrufoption. Der RxJava-Code ist robuster. Überlegen Sie, was passieren würde, wenn ein dritter JSON geladen werden müsste (wie die neuesten Videos)? Der RxJava müsste nur geringfügig angepasst werden, während die Rückrufvariante an mehreren Stellen angepasst werden muss (bei jedem Rückruf müssen wir überprüfen, ob alle Daten abgerufen wurden).
Ein anderes Beispiel; Wir möchten ein Autocomplete-Feld erstellen, das Daten mit Retrofit lädt. Wir möchten nicht jedes Mal einen Webcall durchführen, wenn ein EditText ein TextChangedEvent hat. Bei schneller Eingabe sollte nur das letzte Element den Aufruf auslösen. Auf RxJava können wir den Entprellungsoperator verwenden:
inputObservable.debounce(1, TimeUnit.SECONDS).subscribe(new Action1<String>() {
@Override
public void call(String s) {
// use Retrofit to create autocompletedata
}
});
Ich werde die Callback-Variante nicht erstellen, aber Sie werden verstehen, dass dies viel mehr Arbeit ist.
Fazit: RxJava ist außergewöhnlich gut, wenn Daten als Stream gesendet werden. Das Retrofit Observable überträgt alle Elemente im Stream gleichzeitig. Dies ist an sich im Vergleich zu Callback nicht besonders nützlich. Wenn jedoch mehrere Elemente zu unterschiedlichen Zeiten in den Stream verschoben werden und Sie zeitbezogene Aufgaben ausführen müssen, macht RxJava den Code viel wartbarer.