我正在为我的应用开发网络。所以我决定试试Square的Retrofit。我看到它们支持简单的回调
@GET("/user/{id}/photo")
void getUserPhoto(@Path("id") int id, Callback<Photo> cb);
和RxJava的Observable
@GET("/user/{id}/photo")
Observable<Photo> getUserPhoto(@Path("id") int id);
乍一看,两者都非常相似,但当它实现时,它就变得有趣了……
而简单的回调实现看起来类似于:
api.getUserPhoto(photoId, new Callback<Photo>() {
@Override
public void onSuccess() {
}
});
这是非常简单直接的。而使用Observable,它很快就会变得冗长且相当复杂。
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());
}
但事实并非如此。你仍然需要做这样的事情:
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?
}
});
我是不是遗漏了什么?或者在这种情况下使用可观察对象是错误的?
什么时候会/应该更喜欢Observable而不是简单的回调?
更新
使用改造比上面的例子简单得多,就像@Niels在他的回答中或Jake Wharton的例子项目U2020中所展示的那样。但本质上的问题是不变的——什么时候应该使用一种方式或另一种方式?
使用rxjava,你可以用更少的代码做更多的事情。
让我们假设你想在你的应用中实现即时搜索。
通过回调,你担心取消订阅前一个请求并订阅新请求,自己处理方向更改…我认为这是大量的代码和太啰嗦。
用rxjava非常简单。
public class PhotoModel{
BehaviorSubject<Observable<Photo>> subject = BehaviorSubject.create(...);
public void setUserId(String id){
subject.onNext(Api.getUserPhoto(photoId));
}
public Observable<Photo> subscribeToPhoto(){
return Observable.switchOnNext(subject);
}
}
如果你想实现即时搜索,你只需要监听TextChangeListener并调用photommodel . setuserid (EditText.getText());
在Fragment或activity的onCreate方法中,你订阅了返回photomode . subscribetophoto()的Observable,它会返回一个总是发出由最新的Observable(request)发出的项的Observable。
AndroidObservable.bindFragment(this, photoModel.subscribeToPhoto())
.subscribe(new Action1<Photo>(Photo photo){
//Here you always receive the response of the latest query to the server.
});
此外,如果photommodel是一个单例,例如,您不需要担心方向更改,因为不管您何时订阅,BehaviorSubject都会发出最后一个服务器响应。
通过这几行代码,我们实现了即时搜索和处理方向更改。
你认为你可以用更少的代码实现回调吗?我对此表示怀疑。
在getUserPhoto()的情况下,RxJava的优势不是很大。
但让我们再举一个例子,当你为一个用户获取所有照片时,但只有当图像是PNG时,你不能访问JSON来在服务器端进行过滤。
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) {
// on main thread; callback for each photo, add them to a list or something.
list.add(photo)
}
},
new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
// on main thread; something went wrong
System.out.println("Error! " + throwable);
}
},
new Action0() {
@Override
public void call() {
// on main thread; all photo's loaded, time to show the list or something.
}
});
现在JSON返回Photo的列表。我们将把它们平面映射到单独的项目。通过这样做,我们将能够使用过滤器方法来忽略非PNG的照片。之后,我们将订阅,并为每张照片获取一个回调,一个errorHandler,以及当所有行都完成时的回调。
TLDR
这里的点是;回调只返回成功和失败的回调;RxJava Observable允许你做映射,减少,过滤和更多的事情。
使用rxjava,你可以用更少的代码做更多的事情。
让我们假设你想在你的应用中实现即时搜索。
通过回调,你担心取消订阅前一个请求并订阅新请求,自己处理方向更改…我认为这是大量的代码和太啰嗦。
用rxjava非常简单。
public class PhotoModel{
BehaviorSubject<Observable<Photo>> subject = BehaviorSubject.create(...);
public void setUserId(String id){
subject.onNext(Api.getUserPhoto(photoId));
}
public Observable<Photo> subscribeToPhoto(){
return Observable.switchOnNext(subject);
}
}
如果你想实现即时搜索,你只需要监听TextChangeListener并调用photommodel . setuserid (EditText.getText());
在Fragment或activity的onCreate方法中,你订阅了返回photomode . subscribetophoto()的Observable,它会返回一个总是发出由最新的Observable(request)发出的项的Observable。
AndroidObservable.bindFragment(this, photoModel.subscribeToPhoto())
.subscribe(new Action1<Photo>(Photo photo){
//Here you always receive the response of the latest query to the server.
});
此外,如果photommodel是一个单例,例如,您不需要担心方向更改,因为不管您何时订阅,BehaviorSubject都会发出最后一个服务器响应。
通过这几行代码,我们实现了即时搜索和处理方向更改。
你认为你可以用更少的代码实现回调吗?我对此表示怀疑。