2017-04-17 2 views
1

私はRxJavaの栄光を受け入れ、それを自分のアプリケーションに統合しようとしています。私は累積コストが定義された予算を超えていないコミックを追加するために次のコードを書いています。これを実現するために、私は2つの実装を書いた。カスタムフィルタ演算子RxJava

  1. ため
  2. サブスクリプションを持つ複雑さと背圧がRxAndroid libに既に利用可能な演算子を使用し、主に推奨され Observable.create()を使用します。

私は一瞬Observable.create()にわき取り扱いのサブスクリプションおよびバックプレッシャーを置けば実装は、パフォーマンス、メモリ消費とシンプルさの点では1優れている上でのフィードバックを得るのが大好きですか?

最初の実装:

Observable<Integer> filterObservable = Observable.create(new ObservableOnSubscribe<Integer>() { 
    @Override 
    public void subscribe(ObservableEmitter<Integer> e) throws Exception { 
     Timber.d("filterComicsAccordingToBudget():subscribe"); 
     int pageCountOfComicsWithInBudget = 0; 
     double totalCost = 0.0; 
     for(MarvelComic comic : getMarvelComicsList()) { 
      totalCost += Double.valueOf(comic.getPrice()); 
      Timber.d("totalCost: %s budget: %s priceOfComic: %s", totalCost, budget, comic.getPrice()); 
      if(totalCost > budget) { 
       break; 
      } 
      pageCountOfComicsWithInBudget += Integer.valueOf(comic.getPageCount()); 
      Timber.d("pageCount: %s price: %s comicName: %s totalPages: %s", comic.getPageCount(), comic.getPrice(), comic.getTitle(), pageCountOfComicsWithInBudget); 
      e.onNext(pageCountOfComicsWithInBudget); 
     } 
     e.onComplete(); 
    } 
}); 

filterObservable.subscribeOn(Schedulers.computation()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .subscribe(new Observer<Integer>() { 
     int comicCount = 0; 
     int pageCountOfComicsWithInBudget = 0; 

     @Override 
     public void onSubscribe(Disposable d) { 
      Timber.d("filterComicsAccordingToBudget():onSubscribe"); 
     } 

     @Override 
     public void onNext(Integer pageCountOfComicsWithInBudget) { 
      Timber.d("filterComicsAccordingToBudget():onNext"); 
      comicCount++; 
     } 

     @Override 
     public void onError(Throwable e) { 
      Timber.e("onFilterComicsForBudget:onError() %s", e); 
     } 

     @Override 
     public void onComplete() { 
      Timber.d("filterComicsAccordingToBudget():onComplete"); 
     } 
    } 
}); 

第2の実施:

Observable.fromIterable(getMarvelComicsList()) 
    .map(new Function<MarvelComic, HashMap<String, Double>>() { 
     HashMap<String, Double> myMap = new HashMap<String, Double>(); 
     double count = 0; 

     @Override 
     public HashMap<String, Double> apply(@NonNull MarvelComic marvelComic) throws Exception { 
      myMap.put("price", Double.valueOf(marvelComic.getPrice())); 
      myMap.put("pageCount", Double.valueOf(marvelComic.getPageCount())); 
      myMap.put("comicsCount", count++); 
      return myMap; 
     } 
    }) 
    .takeWhile(new Predicate<HashMap<String, Double>>() { 

     double sum; 

     @Override 
     public boolean test(@NonNull HashMap<String, Double> map) throws Exception { 
      Timber.e("sum is: %s", sum); 
      return (sum += map.get("price")) < 5.00; 
     } 
    }) 
    .subscribe(new Observer<HashMap<String, Double>>() { 

     @Override 
     public void onSubscribe(Disposable d) { 
     } 

     @Override 
     public void onNext(HashMap<String, Double> map) { 
      Timber.e("value in onNext is: %s %s %s", map.get("pageCount"), map.get("price"), map.get("comicsCount")); 
     } 

     @Override 
     public void onError(Throwable e) { 
      Timber.e("onError()!!! %s",e); 
     } 

     @Override 
     public void onComplete() { 
      Timber.e("onComplete()!!!"); 
     } 
    }); 

私ちょっと空想それは私が使用していたより不可欠だと私にはあまり不格好なようですので、最初の実装RxJavaの限られた知識を考えれば、私は完全に間違っているかもしれません。

答えて

5

この種の操作ではカスタムObservableを作成しないでください。通常のRxJava演算子を使用して必要な処理をすべて行うことができます。

は、その場で私はこのような何かをするだろう:

private Observable<Double> getLimitObservable(final double budget) { 
    return Observable.fromIterable(getMarvelComicsList()) 
      .scan(0D, (aDouble, marvelComic) -> aDouble + marvelComic.getPrice()) 
      .takeWhile(aDouble -> aDouble < budget) 
      .skip(1); 
} 

上記のコードは、漫画の価格の合計額を追跡するためのscan(とも呼ばれるアキュムレータ)演算子を使用します。詳細はhereです。したがって、新しいObservableからdouble(合計量を表す)が返されます。その後、条件が真になるまでアイテムの放出を停止するtakeWhileがあります。最終的には、上記Observableが少なくとも1つのアイテムを出力するため(条件が確認される前に)最初のアイテムをスキップしました。

Observable.zip(getLimitObservable(500d), Observable.fromIterable(getMarvelComicsList()), (aDouble, marvelComic) -> marvelComic) 
       .subscribe(marvelComic -> Log.d("test", "comic: " + marvelComic.getName())); 

今、私は各項目のカップルのための新しいアイテムを生成します(ジップ演算子を使用して)新しいもの(最初に観察から1、および第二の1)とし、この中に以前に観察を組み合わせますあなたは、2つの観測値から放出されるアイテムの最小数に等しい数のアイテムを取得します。詳細here

これは、予算の上限に達するまで、リストの最初の漫画のリストを印刷します。

もっと良い解決策があると思いますが、これは単なる例です。

+0

私が書いた2番目のインプリメンテーションにはなぜ行かないのですか? OP –

+0

に書かれている "Second Implementation"の記述は何ですか?述語の中にローカル変数を作成するのは良い考えではありません(機能していないようです)。あなたの作業を行う演算子を使用できます。さらに、私はこのコンテキストで 'HashMap'の使用を理解していません。 – GVillani82

+0

また、 '.create()'の中で 'getMarvelComicList()'を使用することはあまり拡張性がないことに注意してください。たとえば、ある日、サーバからObservable として受け取ることにしました。最初の実装で変更するのは難しいでしょう。あなたの2番目のものか、それとも@ GVillani82が提案していることは、この点でより良いです、それはむしろ簡単な調整になります。 – dimsuz