2016-11-12 7 views
2

(アンドロイド/ Javaのプロ、RxJava /ラムダ初心者)私は、次のPOJO作成しようとしています:RxJava&Retrofit2: '一度の' 組み合わせた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... 
} 

I持って、次のRetrofit2実装:

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

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

最初のObservableProductPojoを返し、結果リストuf urlを繰り返して2番目のObservableに入力してTemplatePojoのリストを取得します。最後に結果はすべて、ビルダーパターンを使用して新しいProductCombinePojoに結合されます。 MVPフレームワークの性質上、問題をさらに複雑にするためには、これはすべてFunc0<<Observable<ProductCombinedPojo>>のRxJavaチェーン実装で行う必要があります。

私は鎖の最後にきちんとオリジナルのProductPojoをビルダーに注入するのが難しいです。ここに私の作業が、醜いソリューション(mUrlmProductApi & mTemplateApiは全て上記のように注入され、定義されていると仮定)である:私は醜いfinal ProductPojo[]を必要としないように

@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(); 
      } 
     }); 
} 

は、どのように私はこれを書き換えるのですか? exhuastive検索とこのフォーラムに多くの類似の質問を確認した後、私は思います

Func2<ProductPojo, List<TemplatePojo>, ProductCombinedPojo> 

はどこかに接続する必要がありますが、私は正確にどこ把握することはできません。私はラムダソリューションがどのようなものになるか興味を持っていますが、正解は上記のフォーマットを使用するソリューションに与えられます。

+0

一般的に、あなたが明示的に作成せずに2つ(またはそれ以上)の要素を組み合わせることができ、「組み合わせpojo "のようなタプルを使用しています:http://www.javatuples.org – EpicPandaForce

+0

最終的に明示的なpojoまたはTupleを返したかどうかに関わらず、何らかの形でオペレーターチェーンの下で' ProductPojo'をバブルする必要があります。 nhaarmanは以下の 'Pair' Tupleについて言及しています。私は最初の 'flatMap'でタプルの組み合わせを作ることを考えました。問題は、その後の 'flatMapIterable'や' from'の出力が反復可能でなければならないことです。タプルはそのまま使えます(私が間違っていれば私を修正します)。 –

答えて

1

mapまたはflatMapのようなすべての操作では、の入力を新しい出力に変換するという問題があります。入力を出力に含めないと、後でその入力にアクセスすることができなくなります。 これはあなたがここで直面していることです:ProductPojoにストリームからさらにアクセスしたいと思っています。

flatMapIterable関数でPair<ProductPojo, List<String>>を返すことでこれを回避することができますが、これも改善されません。

代わりに、あなたのProductPojoの範囲に新しいObservableを作成することができます。

ラムダを使用して
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(); 
       } 
      }); 
} 

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() 
     )); 
} 
+0

これは、私の解決策よりもやり方です - 本質的には同じですが(ProductPojoは最終版に保存されます)。私は本当に、このシナリオを満たす観察可能なオペレータの膨大な武器に何かが存在することを期待していました。このような明確な答えを出すために時間と努力を尽くしてくれてありがとう。私はそれが受け入れられたと確かめるでしょう。 –

関連する問題