我正在为我的应用开发网络。所以我决定试试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中所展示的那样。但本质上的问题是不变的——什么时候应该使用一种方式或另一种方式?


当前回答

Observable的东西已经在Retrofit中完成了,所以代码可以是这样的:

api.getUserPhoto(photoId)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<Photo>() {
         @Override
            public void call(Photo photo) {
                //save photo?
            }
     });

其他回答

我个人更喜欢使用Rx来获得api响应的情况下,我必须做过滤,映射或类似的数据或在情况下,我必须做另一个api调用基于之前的调用响应

看起来你在重新发明轮子,你所做的已经在改造中实现了。

举个例子,你可以看看retrofit的RestAdapterTest.java,在那里他们定义了一个接口,将Observable作为返回类型,然后使用它。

当你为乐趣、宠物项目、POC或第一个原型创建应用时,你会使用简单的android/java核心类,如回调、异步任务、循环器、线程等。它们使用简单,不需要任何第三方lib集成。当类似的事情可以立即完成时,仅仅为了构建一个小型的不可更改的项目而进行大型库集成是不合逻辑的。

然而,这些就像一把非常锋利的刀。在生产环境中使用这些工具总是很酷,但也会产生一些后果。如果不熟悉Clean编码和SOLID原则,就很难编写安全的并发代码。您必须维护一个适当的体系结构,以促进未来的变更和提高团队生产力。

另一方面,像RxJava、co -routine等并发库已经被尝试和测试了超过十亿次,以帮助编写可用于生产的并发代码。现在再次强调,并不是说使用这些库就不能编写并发代码或抽象出所有并发逻辑。你现在还是。但是现在,它是可见的,并且在整个代码库中,更重要的是在整个开发团队中,执行了一个清晰的并发代码编写模式。

这是使用并发框架而不是处理原始并发的普通旧核心类的主要好处。不过,别误会我的意思。我非常相信限制外部库的依赖关系,但在这种特定情况下,你必须为你的代码库构建一个自定义框架,这是一项耗时的任务,只有在有了丰富的经验之后才能完成。因此,与使用回调等普通类相比,并发框架更受欢迎。


TL 'DR

如果你已经在整个代码库中使用RxJava进行并发编码,只需使用RxJava Observable/Flowable即可。一个明智的问题是我应该使用可观察对象还是可流动对象。 如果不是,继续使用可调用对象。

我们通常遵循以下逻辑:

如果它是一个简单的单响应调用,那么Callback或Future更好。 如果一个调用有多个响应(流),或者不同调用之间有复杂的交互(参见@Niels的回答),那么Observables更好。

Observable的东西已经在Retrofit中完成了,所以代码可以是这样的:

api.getUserPhoto(photoId)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<Photo>() {
         @Override
            public void call(Photo photo) {
                //save photo?
            }
     });