(Android / Java专业人士,RxJava / Lambda新手)我正在尝试创建以下pojo:

public class ProductCombinedPojo {
    private ProductPojo product;
    private List<TemplatePojo> templates;

    // builder pattern...
}


其中ProductPojo是:

public class ProductPojo {
    private List<String> templateUrls; // each url returns a TemplatePojo

    // lots of other stuff...
}


我有以下Retrofit2实现:

@GET
Observable<ProductPojo> getProduct(@Url String url);

@GET
Observable<TemplatePojo> getTemplate(@Url String url);


因此,第一个Observable返回ProductPojo,遍历其中的结果列表uf url,并将其输入到第二个Observable以获取TemplatePojo的列表,最后将结果全部合并为一个新的使用构建器模式。由于MVP框架的性质,使问题进一步复杂化,所有这些都必须在单个ProductCombinePojo链接的RxJava实现中完成。

在链的末尾,我很难将原始的Func0<<Observable<ProductCombinedPojo>>注入到构建器中。这是我工作但很丑陋的解决方案(假设ProductPojomUrlmProductApi都已注入并定义如上):

@Override
public Observable<ProductCombinedPojo> call() {
    final ProductPojo[] aProductPojo = new ProductPojo[1]; // <------------ Ugly!
    return mProductApi
        .getProduct(mUrl)
        .flatMapIterable(new Func1<ProductPojo, List<String>>() {
            @Override
            public List<String> call(ProductPojo productPojo) {
                aProductPojo[0] = productPojo;             // <------------ Ugly!
                return productPojo.getTemplateUrls();
            }
        })
        .flatMap(new Func1<String, Observable<TemplatePojo>>(){
            @Override
            public Observable<TemplatePojo> call(String templateUrl) {
                return mTemplateApi.getTemplate(templateUrl);
            }
        })
        .toList()
        .map(new Func1<List<TemplatePojo>, ProductCombinedPojo>() {
            @Override
            public ProductCombinedPojo call(List<TemplatePojo> templatePojos) {
                return ProductCombinedPojo.Builder.aProductCombinedPojo()
                        .product(aProductPojo[0])          // <------------ Ugly!
                        .templates(templatePojos)
                        .build();
            }
        });
}


我该如何重写它,以便不需要丑陋的mTemplateApi?经过认真地搜索和审查了该论坛上的许多类似问题之后,我认为

Func2<ProductPojo, List<TemplatePojo>, ProductCombinedPojo>


应该插入某个地方,但我不知道确切的位置。尽管我对Lambda解决方案的外观很感兴趣,但使用上述格式的任何解决方案都将获得正确的答案。

最佳答案

问题在于,对于每个操作,如mapflatMap,您都将输入转换为新的输出。如果您未在输出中包含输入,则以后将无法访问该输入。
这就是您在此处面临的问题:您希望能够在流的更下游访问ProductPojo

您可以通过在Pair<ProductPojo, List<String>>函数中返回flatMapIterable来规避此问题,但这也没有任何改善。

相反,您可以在Observable的范围内创建一个新的ProductPojo

public Observable<ProductCombinedPojo> call() {
    return mProductApi.getProduct(mUrl)
          .flatMap(new Func1<ProductPojo, Observable<ProductCombinedPojo>>() {
              @Override
              public Observable<ProductCombinedPojo> call(ProductPojo productPojo) {
                  return combinedPojoFor(productPojo);
              }
          });
}

private Observable<ProductCombinedPojo> combinedPojoFor(final ProductPojo productPojo) {
    return Observable.from(productPojo.getTemplateUrls())
          .flatMap(new Func1<String, Observable<TemplatePojo>>() {
              @Override
              public Observable<TemplatePojo> call(String templateUrl) {
                  return mTemplateApi.getTemplate(templateUrl);
              }
          })
          .toList()
          .map(new Func1<List<TemplatePojo>, ProductCombinedPojo>() {
              @Override
              public ProductCombinedPojo call(List<TemplatePojo> templatePojos) {
                  return ProductCombinedPojo.Builder.aProductCombinedPojo()
                        .product(productPojo)
                        .templates(templatePojos)
                        .build();
              }
          });
}


使用lambda:

public Observable<ProductCombinedPojo> call() {
    return mProductApi.getProduct(mUrl)
        .flatMap((productPojo) -> combinedPojoFor(productPojo));
}

private Observable<ProductCombinedPojo> combinedPojoFor(final ProductPojo productPojo) {
    return Observable.from(productPojo.getTemplateUrls())
        .flatMap((templateUrl) -> mTemplateApi.getTemplate(templateUrl))
        .toList()
        .map((templatePojos ->
            ProductCombinedPojo.Builder.aProductCombinedPojo()
                .product(productPojo)
                .templates(templatePojos)
                .build()
        ));
}

08-18 06:31