如何映射从 observable 返回的值以用于另一个 observable
how to map values returned from observable to be used in another observable
我有以下 observable 可以从数据库中获取 feed id 列表(我使用 sugar ORM 库)
public Observable<Set<Long>> getFeedIdsFromDB() {
return Observable.create(subscriber -> {
Set<Integer> subscribedFeedIds = new HashSet<>();
//get feed ids from FeedEntity Table
for (FeedEntity feed : FeedEntity.listAll(FeedEntity.class)){
if (feed.isSubscribed()){
subscribedFeedIds.add(feed.getFeedId());
}
}
});
}
此 Observable 应发出用于以下 api 调用的 ID:
public Observable<StoryCollectionEntity> storyEntityList(final int page) {
return this.restApi.storyCollection(/* this is feed ids*/ id, page)
.distinct(storyCollectionEntity -> storyCollectionEntity)
.doOnNext(saveStoryCollectionToCacheAction)
}
我想我应该使用某种映射,但不知道如何实现它。
编辑:
我做了以下修改:
// To map feed ids (retrieved from database) to getAllStoryEntityList Observable:
@Override
public Observable<StoryCollectionEntity> storyEntityList(final int page) {
return this.mNewsCache.getFeedIdsFromDB().flatMap(id -> getAllStoryEntityList(page, id));
}
//call restApi
public Observable<StoryCollectionEntity> getAllStoryEntityList(final int page, Set<Long> id){
return this.restApi.storyCollection( id, page)
.distinct(storyCollectionEntity -> storyCollectionEntity)
.doOnNext(saveStoryCollectionToCacheAction);
}
但 api 服务从未被调用。映射有问题。
@GET("story")
Observable<StoryCollectionEntity> storyCollection(
@Query("feed_ids") Set<Long> feedIds,
@Query("page") int page);
我不确定预期的输出是什么,但我会向您展示一种执行此类操作的方法。也许您可以更改它以适合您的用例。
第一步是允许id
作为storyEntityList
中的函数参数:
public Observable<StoryCollectionEntity> storyEntityList(final int page, int id) {
return this.restApi.storyCollection(/* this is feed ids*/ id, page)
.distinct(storyCollectionEntity -> storyCollectionEntity)
.doOnNext(saveStoryCollectionToCacheAction)
现在您可以使用 Observable.flatMap
:
public Observable<StoryCollectionEntity> getAllStoryEntityList(int page){
return getFeedIdsFromDB().flatMap(id -> storyEntityList(page, id));
}
命名可能有误,但同样 - 我不确定实体是什么。
在 getFeedIdsFromDB
中创建的 Observable 没有发射任何项目,所以你的 flatMap 和其他数据转换永远不会发生,因为流实际上没有 data。您可以通过直接订阅返回的 Observable 并为 onNext 做一些事情来测试它。
getFeedIdsFromDB().subscribe(feedId -> System.out.println(feedId));
您应该会看到没有打印任何内容。当使用 Observable#create
时,匿名 class 中 subscriber
的 onNext 方法必须用您希望传递给下游的任何数据手动调用。文档为此提供了示例代码。
所以修改你的 Observable 来调用 onNext,我们得到这个:
public Observable<Set<Long>> getFeedIdsFromDB() {
return Observable.create(subscriber -> {
Set<Integer> feedIds = new HashSet<>();
// get feed ids from FeedEntity Table
for (FeedEntity feed : FeedEntity.listAll(FeedEntity.class)){
feedIds.add(feed.getFeedId());
}
// emit a single Set and complete
if (subscriber.isSubscribed()) {
subscriber.onNext(feedIds);
subscriber.onCompleted();
}
});
}
现在 Set
应该被传递了。如果您的目标是在转换后最终发射单个 StoryCollectionEntity
对象(如果我没看错的话),那么您的映射看起来是正确的。
我有以下 observable 可以从数据库中获取 feed id 列表(我使用 sugar ORM 库)
public Observable<Set<Long>> getFeedIdsFromDB() {
return Observable.create(subscriber -> {
Set<Integer> subscribedFeedIds = new HashSet<>();
//get feed ids from FeedEntity Table
for (FeedEntity feed : FeedEntity.listAll(FeedEntity.class)){
if (feed.isSubscribed()){
subscribedFeedIds.add(feed.getFeedId());
}
}
});
}
此 Observable 应发出用于以下 api 调用的 ID:
public Observable<StoryCollectionEntity> storyEntityList(final int page) {
return this.restApi.storyCollection(/* this is feed ids*/ id, page)
.distinct(storyCollectionEntity -> storyCollectionEntity)
.doOnNext(saveStoryCollectionToCacheAction)
}
我想我应该使用某种映射,但不知道如何实现它。
编辑: 我做了以下修改:
// To map feed ids (retrieved from database) to getAllStoryEntityList Observable:
@Override
public Observable<StoryCollectionEntity> storyEntityList(final int page) {
return this.mNewsCache.getFeedIdsFromDB().flatMap(id -> getAllStoryEntityList(page, id));
}
//call restApi
public Observable<StoryCollectionEntity> getAllStoryEntityList(final int page, Set<Long> id){
return this.restApi.storyCollection( id, page)
.distinct(storyCollectionEntity -> storyCollectionEntity)
.doOnNext(saveStoryCollectionToCacheAction);
}
但 api 服务从未被调用。映射有问题。
@GET("story")
Observable<StoryCollectionEntity> storyCollection(
@Query("feed_ids") Set<Long> feedIds,
@Query("page") int page);
我不确定预期的输出是什么,但我会向您展示一种执行此类操作的方法。也许您可以更改它以适合您的用例。
第一步是允许id
作为storyEntityList
中的函数参数:
public Observable<StoryCollectionEntity> storyEntityList(final int page, int id) {
return this.restApi.storyCollection(/* this is feed ids*/ id, page)
.distinct(storyCollectionEntity -> storyCollectionEntity)
.doOnNext(saveStoryCollectionToCacheAction)
现在您可以使用 Observable.flatMap
:
public Observable<StoryCollectionEntity> getAllStoryEntityList(int page){
return getFeedIdsFromDB().flatMap(id -> storyEntityList(page, id));
}
命名可能有误,但同样 - 我不确定实体是什么。
在 getFeedIdsFromDB
中创建的 Observable 没有发射任何项目,所以你的 flatMap 和其他数据转换永远不会发生,因为流实际上没有 data。您可以通过直接订阅返回的 Observable 并为 onNext 做一些事情来测试它。
getFeedIdsFromDB().subscribe(feedId -> System.out.println(feedId));
您应该会看到没有打印任何内容。当使用 Observable#create
时,匿名 class 中 subscriber
的 onNext 方法必须用您希望传递给下游的任何数据手动调用。文档为此提供了示例代码。
所以修改你的 Observable 来调用 onNext,我们得到这个:
public Observable<Set<Long>> getFeedIdsFromDB() {
return Observable.create(subscriber -> {
Set<Integer> feedIds = new HashSet<>();
// get feed ids from FeedEntity Table
for (FeedEntity feed : FeedEntity.listAll(FeedEntity.class)){
feedIds.add(feed.getFeedId());
}
// emit a single Set and complete
if (subscriber.isSubscribed()) {
subscriber.onNext(feedIds);
subscriber.onCompleted();
}
});
}
现在 Set
应该被传递了。如果您的目标是在转换后最终发射单个 StoryCollectionEntity
对象(如果我没看错的话),那么您的映射看起来是正确的。