(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>>
注入到构建器中。这是我工作但很丑陋的解决方案(假设ProductPojo
,mUrl
和mProductApi
都已注入并定义如上):@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解决方案的外观很感兴趣,但使用上述格式的任何解决方案都将获得正确的答案。
最佳答案
问题在于,对于每个操作,如map
或flatMap
,您都将输入转换为新的输出。如果您未在输出中包含输入,则以后将无法访问该输入。
这就是您在此处面临的问题:您希望能够在流的更下游访问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()
));
}