Para cosas de redes simples, las ventajas de RxJava sobre Callback son muy limitadas. El simple ejemplo 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
}
});
Llamar de vuelta:
api.getUserPhoto(photoId, new Callback<Photo>() {
@Override
public void onSuccess(Photo photo, Response response) {
}
});
La variante RxJava no es mucho mejor que la variante Callback. Por ahora, ignoremos el manejo de errores. Tomemos una lista de 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)
}
});
Llamar de vuelta:
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);
}
}
}
});
Ahora, la variante RxJava todavía no es más pequeña, aunque con Lambdas se acercaría más a la variante Callback. Además, si tiene acceso al feed JSON, sería un poco extraño recuperar todas las fotos cuando solo se muestran los PNG. Simplemente ajuste el feed para que solo muestre PNG.
Primera conclusión
No hace que su base de código sea más pequeña cuando está cargando un JSON simple que preparó para estar en el formato correcto.
Ahora, hagamos las cosas un poco más interesantes. Supongamos que no solo desea recuperar el userPhoto, sino que tiene un clon de Instagram y desea recuperar 2 JSON: 1. getUserDetails () 2. getUserPhotos ()
Desea cargar estos dos JSON en paralelo, y cuando se cargan ambos, se debe mostrar la página. La variante de devolución de llamada se volverá un poco más difícil: debe crear 2 devoluciones de llamada, almacenar los datos en la actividad y, si todos los datos están cargados, mostrar la página:
Llamar de vuelta:
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) {
}
});
Estamos llegando a alguna parte! El código de RxJava ahora es tan grande como la opción de devolución de llamada. El código RxJava es más robusto; ¿Piensa en lo que sucedería si necesitáramos cargar un tercer JSON (como los últimos videos)? El RxJava solo necesitaría un pequeño ajuste, mientras que la variante de devolución de llamada debe ajustarse en varios lugares (en cada devolución de llamada debemos verificar si se recuperan todos los datos).
Otro ejemplo; queremos crear un campo de autocompletar, que carga datos usando Retrofit. No queremos hacer una llamada web cada vez que un EditText tenga un TextChangedEvent. Al escribir rápido, solo el último elemento debe activar la llamada. En RxJava podemos usar el operador antirrebote:
inputObservable.debounce(1, TimeUnit.SECONDS).subscribe(new Action1<String>() {
@Override
public void call(String s) {
// use Retrofit to create autocompletedata
}
});
No crearé la variante de devolución de llamada, pero comprenderá que esto es mucho más trabajo.
Conclusión: RxJava es excepcionalmente bueno cuando los datos se envían como una secuencia. El Retrofit Observable empuja todos los elementos en la secuencia al mismo tiempo. Esto no es particularmente útil en sí mismo en comparación con la devolución de llamada. Pero cuando hay varios elementos empujados en la transmisión y en diferentes momentos, y necesita hacer cosas relacionadas con el tiempo, RxJava hace que el código sea mucho más fácil de mantener.