问题描述
我的工作网络为我的应用程序。 Desided尝试广场的改造。我看到他们支持简单的回调
I'm working on networking for my app. Desided to try out Square's Retrofit. I see that they support simple Callback
@GET("/user/{id}/photo")
void getUserPhoto(@Path("id") int id, Callback<Photo> cb);
和RxJava的观测
@GET("/user/{id}/photo")
Observable<Photo> getUserPhoto(@Path("id") int id);
乍一看类似,都看pretty的。但是,当它到达执行变得有趣起来......
Both look pretty similar at first glance. But when it gets to implementation it gets interesting...
而用简单的回调实现将类似于此:
While with simple callback implementation would look similar to this:
api.getUserPhoto(photoId, new Callback<Photo>() {
@Override
public void onSuccess() {
}
});
这是相当简单明了。并与观测
它很快变得冗长且相当复杂的。
which is quite simple and straightforward. And with Observable
it quickly gets verbose and quite complicated.
public Observable<Photo> getUserPhoto(final int photoId) {
return Observable.create(new Observable.OnSubscribeFunc<Photo>() {
@Override
public Subscription onSubscribe(Observer<? super Photo> observer) {
try {
observer.onNext(api.getUserPhoto(photoId));
observer.onCompleted();
} catch (Exception e) {
observer.onError(e);
}
return Subscriptions.empty();
}
}).subscribeOn(Schedulers.threadPoolForIO());
}
这是不是。你仍然需要做这样的事情:
And that is not it. You still have to do something like this:
Observable.from(photoIdArray)
.mapMany(new Func1<String, Observable<Photo>>() {
@Override
public Observable<Photo> call(Integer s) {
return getUserPhoto(s);
}
})
.subscribeOn(Schedulers.threadPoolForIO())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Photo>() {
@Override
public void call(Photo photo) {
//save photo?
}
});
我失去了一些东西呢?或者这是一个错误的情况下使用观测
S'何时/人应该preFER 观测
过简单的回调?
Am I missing something here? Or is this a wrong case to use Observable
s?When would/should one prefer Observable
over simple Callback?
使用翻新比上面的例子如@Niels显示,他的回答还是杰克沃顿商学院的示例项目 U2020 的要简单得多。但本质上的问题保持不变 - ?当一个人应该用一种方式或其他
Using retrofit is much simpler than example above as @Niels showed in his answer or in Jake Wharton's example project U2020. But essentially the question stays the same - when should one use one way or the other?
推荐答案
对于简单的网络的东西,RxJava过回调的优点是非常有限的。简单getUserPhoto例如:
For simple networking stuff, the advantages of RxJava over Callback is very limited. The simple getUserPhoto example:
RxJava:
api.getUserPhoto(photoId)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Photo>() {
@Override
public void call(Photo photo) {
}
});
回调:
api.getUserPhoto(photoId, new Callback<Photo>() {
@Override
public void onSuccess(Photo photo, Response response) {
}
});
的RxJava变体并不比回拨变种好得多。现在,让我们忽略了errorhandling。让我们的照片清单:
The RxJava variant is not much better than the Callback variant. For now, let's ignore the errorhandling.Let's take a list of 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)
}
});
回调:
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);
}
}
}
});
现在,该RxJava变种仍然不小,虽然和λ的它是对子级吸气接近回调的变体。此外,如果你有机会到JSON的饲料,这将是一种奇怪的检索所有的照片时,你只显示PNG的。只需调整饲料只显示PNG的。
Now, the RxJava variant still isn't smaller, although with Lambda's it whould be getter closer to the Callback variant.Furthermore, if you have access to the JSON feed, it would be kind of weird to retrieve all photos when you're only displaying the PNG's. Just adjust the feed to it only displays PNG's.
第一个结论的
这是没有,当你加载你prepared是在正确的格式简单的JSON您的codeBase的更小。
It doesn't make your codebase smaller when you're loading a simple JSON that you prepared to be in the right format.
现在,让我们来让事情变得更有趣一点。比方说,你不仅要检索的userPhoto,但你有一个Instagram的克隆,并要恢复2 JSON的:1. getUserDetails()2. getUserPhotos()
Now, let's make things a bit more interesting. Let's say you not only want to retrieve the userPhoto, but you have an Instagram-clone, and you want to retrieve 2 JSON's:1. getUserDetails()2. getUserPhotos()
您希望加载这两个JSON的并行,而当两者都装,要显示的页面。回调变种会变得有点难度:你必须创建2回调,将数据存储在活动,如果加载的所有数据,显示页面:
You want to load these two JSON's in parallel, and when both are loaded, the page should be displayed.The callback variant will become a bit more difficult: you have to create 2 callbacks, store the data in the activity, and if all the data is loaded, display the page:
回调:
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) {
}
});
我们要去哪里! RxJava的code是现在一样大的回调选项。该RxJava code是更加强劲;想想,如果我们需要第三JSON加载(如最新的影片)会发生什么?该RxJava只需要一个小的调整,而回调的变体需要在多个地方进行调整(上,我们需要检查是否所有的数据检索每次回调)。
We are getting somewhere! The code of RxJava is now as big as the callback option. The RxJava code is more robust;Think of what would happen if we needed a third JSON to be loaded (like the latest Videos)? The RxJava would only need a tiny adjustment, while the Callback variant needs to be adjusted in multiple places (on each callback we need to check if all data is retrieved).
又如;我们想创建一个自动完成场,利用改造它加载数据。我们不希望每一个EditText有一个TextChangedEvent时间做webcall。当打字速度快,只有最后一个元素会触发通话。在RxJava我们可以使用去抖操作符:
Another example; we want to create an autocomplete field, which loads data using Retrofit.We don't want to do a webcall every time an EditText has a TextChangedEvent. When typing fast, only the last element should trigger the call.On RxJava we can use the debounce operator:
inputObservable.debounce(1, TimeUnit.SECONDS).subscribe(new Action1<String>() {
@Override
public void call(String s) {
// use Retrofit to create autocompletedata
}
});
我不会创建回调变量,但你会明白这是很多工作。
I won't create the Callback variant but you will understand this is much more work.
结论:RxJava出奇的好,当数据被作为流。改造观测推的同时流上的所有元素。相比回调这本身不是特别有用。但是,当有推流和不同的时间多个元素,而你需要做的时机相关的东西,RxJva使得codeA更多的维护。
Conclusion:RxJava is exceptionally good when data is sent as a stream. The Retrofit Observable pushes all elements on the stream at the same time.This isn't particularly useful in itself compared to Callback. But when there are multiple elements pushed on the stream and different times, and you need to do timing-related stuff, RxJva makes the code a lot more maintainable.
这篇关于当一个人应该使用RxJava观测,当简单的回调在Android?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!