使用RxJava和Retrofit迭代列表并根据子查询扩充结果

时间:2015-05-14 10:50:11

标签: android retrofit rx-java retrolambda

我正在使用改装,我觉得rxjava(with retrolambda)非常适合以下流程:

  1. 获取小部件列表(http)
  2. 每个小部件
  3. a)获取给定窗口小部件类型的文章列表(http) b)将所有这些保存到db
    c)获取列表中的第一篇(最新)文章,并使用本文中的适当值更新widget.articleName和widget.articleUrl

  4. 转换回列表并完成
  5. 但是我不确定在步骤2a之后该怎么做。到目前为止,这是我的代码

    apiService.getWidgets(token)
      .flatMapIterable(widgets -> widgets)
      .flatMap(widget -> apiService.getArticles(token, widget.type))
      ...
      .toList()
      .subscribe(
         modifiedWidgets -> saveWidgets(modifiedWidgets),
         throwable -> processWidgetError(throwable)
      );
    

    我和一些运营商玩过,但是在链接时,我似乎总是缩小范围   太远了(例如,获取单个文章的句柄)然后再也无法访问   原始小部件进行修改。

    @GET("/widgets")
    Observable<List<Widget>> getWidgets(@Header("Authorization") String token);
    
    @GET("/articles")
    Observable<List<Article>> getArticles(@Header("Authorization") String token, @Query("type") String type);
    

3 个答案:

答案 0 :(得分:21)

您可以在流的某些位置插入doOnNext以添加副作用:

apiService.getWidgets(token)
.flatMapIterable(v -> v)
.flatMap(w -> 
    apiService.getArticles(token, w.type)
    .flatMapIterable(a -> a)
    .doOnNext(a -> db.insert(a))
    .doOnNext(a -> {
         w.articleName = a.name;
         w.articleUrl = a.url;
    })
    .takeLast(1)
    .map(a -> w)
)
.toList()
.subscribe(
    modifiedWidgets -> saveWidgets(modifiedWidgets),
    throwable -> processWidgetError(throwable)
);

Here is可运行的例子。

答案 1 :(得分:1)

在此处添加此内容,因为我无法找到将对象中返回的列表作为变量进行迭代的示例。

getUserAccount(token)
    .subscribeOn(Schedulers.newThread())
    .observeOn(AndroidSchedulers.mainThread())
    .flatMap(userResponse -> Observable.just(userResponse.list))      //get list from response
    .flatMapIterable(baseDatas -> baseDatas)                          //make the list iterable
    .flatMap(baseData ->                                              //on each project, get the details
            getProjectDetails(baseData.name,token)
                    .subscribeOn(Schedulers.io())                     //get network call off the main thread
                    .observeOn(AndroidSchedulers.mainThread()))
    .subscribe(
            (dataResponse) -> {
                Timber.d( "Got Data Details:" + dataResponse);
            },
            (error) -> {
                Timber.e( "Got Error:" + error.getMessage());
            },
            () -> {
                Timber.d("Completed Data Details");
            }
    );

答案 2 :(得分:0)

akarnokd的答案非常有用,但可能会导致NetworkOnMainThreadException。 要解决这个问题,我已经添加了

.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
每次请求

apiService.getWidgets(token)
.observeOn(AndroidSchedulers.mainThread())      //added this
.subscribeOn(Schedulers.io())                   //added this
.flatMapIterable(v -> v)
.flatMap(w -> 
    apiService.getArticles(token, w.type)
    .observeOn(AndroidSchedulers.mainThread())  //added this
    .subscribeOn(Schedulers.io())               //added this
    .flatMapIterable(a -> a)
    .doOnNext(a -> db.insert(a))
    .doOnNext(a -> {
         w.articleName = a.name;
         w.articleUrl = a.url;
    })
    .takeLast(1)
    .map(a -> w)
)
.toList()
.subscribe(
    modifiedWidgets -> saveWidgets(modifiedWidgets),
    throwable -> processWidgetError(throwable)
);