Para coisas simples de rede, as vantagens do RxJava sobre o retorno de chamada são muito limitadas. O exemplo simples 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
}
});
Ligue de volta:
api.getUserPhoto(photoId, new Callback<Photo>() {
@Override
public void onSuccess(Photo photo, Response response) {
}
});
A variante RxJava não é muito melhor que a variante de retorno de chamada. Por enquanto, vamos ignorar o tratamento de erros. Vamos tirar uma 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)
}
});
Ligue de volta:
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);
}
}
}
});
Agora, a variante RxJava ainda não é menor, embora, com o Lambdas, ele fique mais próximo da variante de retorno de chamada. Além disso, se você tiver acesso ao feed JSON, seria meio estranho recuperar todas as fotos quando estiver exibindo apenas os PNGs. Basta ajustar o feed para exibir apenas PNGs.
Primeira conclusão
Isso não diminui sua base de código quando você está carregando um JSON simples que você preparou para estar no formato certo.
Agora, vamos tornar as coisas um pouco mais interessantes. Digamos que você não apenas deseja recuperar a foto do usuário, mas também possui um clone do Instagram e deseja recuperar 2 JSONs: 1. getUserDetails () 2. getUserPhotos ()
Você deseja carregar esses dois JSONs em paralelo e, quando ambos são carregados, a página deve ser exibida. A variante de retorno de chamada se tornará um pouco mais difícil: você precisará criar dois retornos de chamada, armazenar os dados na atividade e, se todos os dados estiverem carregados, exibir a página:
Ligue de volta:
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 chegando a algum lugar! O código do RxJava agora é tão grande quanto a opção de retorno de chamada. O código RxJava é mais robusto; Pense no que aconteceria se precisássemos carregar um terceiro JSON (como os vídeos mais recentes)? O RxJava precisaria apenas de um pequeno ajuste, enquanto a variante de retorno de chamada precisa ser ajustada em vários locais (em cada retorno de chamada, precisamos verificar se todos os dados são recuperados).
Outro exemplo; queremos criar um campo de preenchimento automático, que carrega dados usando o Retrofit. Não queremos fazer uma chamada da Web toda vez que um EditText tiver um TextChangedEvent. Ao digitar rápido, apenas o último elemento deve acionar a chamada. No RxJava, podemos usar o operador debounce:
inputObservable.debounce(1, TimeUnit.SECONDS).subscribe(new Action1<String>() {
@Override
public void call(String s) {
// use Retrofit to create autocompletedata
}
});
Não vou criar a variante de retorno de chamada, mas você entenderá que isso é muito mais trabalhoso.
Conclusão: RxJava é excepcionalmente bom quando os dados são enviados como um fluxo. O Retrofit Observable empurra todos os elementos no fluxo ao mesmo tempo. Isso não é particularmente útil em comparação com o retorno de chamada. Mas quando existem vários elementos enviados no fluxo e em horários diferentes, e você precisa fazer coisas relacionadas ao tempo, o RxJava torna o código muito mais sustentável.