2016-10-15 12 views
1

これは、短い例で最もよく説明されています。
だが、これは私がフィルタ状態を処理するために、チェックボックスを使用しある観測値の状態を使用して、別の観測値の値をスキップする方法はありますか?

Observable.interval(1, TimeUnit.SECONDS) 

をフィルタリングすることを観察できる私の源であるとしましょう。ボックスがチェックされていない場合は、すべての値をスキップします。
私はこのようなチェックボックスのために観察取得するRxAndroidを使用します。私はちょうど午前

Observable.combineLatest(
      RxCompoundButton.checkedChanges(checkBox) 
      , Observable.interval(1, TimeUnit.SECONDS) 
      , (isChecked, intervalCounter) -> { 
       if (!isChecked) { 
        return null; 
       } else { 
        return intervalCounter; 
       } 
      } 
    ).filter(Objects::nonNull) 

と私は、所望の出力

interval  1--2--3--4--5--6--7--8--9 
checkbox  0-----1--------0-----1--- 
combineLatest 
result   ------3--4--5--------8--9 

を得る:ここ

RxCompoundButton.checkedChanges(checkBox) 

は私のコードですRxJavaを使い始めると私の "解決策"が正しく感じられません:
あなたは、 ctionはマジック値nullを返し、フィルタはこれらをスキップしますnulls
これは、私が既に知っていてもフィルタ関数が呼び出され、このデータをスキップしたいということです。

  • 多分私は
  • は、多分私はこのデータをスキップすることを知らせるために機能を組み合わせることで、いくつかの方法があり、チェックボックス、観察可能なフィルタ機能でを使用する方法がある別のオペレータ
  • を使用する必要があります

答えて

2

希望する出力の写真が正しくありません。あなたの実装ではcombineLatestは、ストリームにnullを組み合わせている:

interval  1--2--3--4--5--6--7--8--9 
checkbox  0-----1--------0-----1--- 
combineLatest N--N--3--4--5--N--N--8--9 
filter(NonNull)------3--4--5--------8--9 

私見を、信号が受信ストリームでは良くないようnullを使用して、開発者は簡単にNullPointerExceptionに分類することができます。

nullの使用を避けるには、2つの方法があります。 1つ目は、結果をペアに変換し、後で&フィルタを適用することです。

A非常に単純なPairクラス:

public class Pair<T, U> { 
    T first; 
    U second; 

    public Pair(T first, U second) { 
     this.first = first; 
     this.second = second; 
    } 
} 

は、その後、全体の実装は、このことを希望:

Observable.combineLatest(
     RxCompoundButton.checkedChanges(checkBox) 
     , Observable.interval(1, TimeUnit.SECONDS) 
     , (isChecked, intervalCounter) -> new Pair<>(isChecked,intervalCounter) 
).filter(pair -> pair.first) 
.map(pair -> pair.second) // optional, do this if you only need the second part 

データフロー:

interval   1  2  3  4 
        |  |  |  | 
checkbox  F | T | F | T F 
        | | | | | | | 
combineLatest F1 T1 T2 F2 F3 T3 F4 
        | |   | 
filter(first=T)  T1 T2  T3 
        | |   | 
map(second)   1 2   3 

それとも、できればJavaの8中あなたのプロジェクトは、を使用してnullを避けてください。あなたのソリューションに非常によく似ていますが、ストリーム信号がOptionalであることを他の開発者に知らせるものです。

Observable<Optional<Integer>> o1 = Observable.combineLatest(
     RxCompoundButton.checkedChanges(checkBox) 
     , Observable.interval(1, TimeUnit.SECONDS) 
     , (isChecked, intervalCounter) -> { 
      if (!isChecked) { 
       return Optional.empty(); 
      } else { 
       return Optional.of(intervalCounter); 
      } 
     } 
) 

Observable<Integer> o2 = o1.filter(Optional::isPresent).map(Optional::get) 

combineLatestと同じではありませんが、希望する結果画像と同じではない簡単なアプローチです。

// Approach 1 
Observable.interval(1, TimeUnit.SECONDS).filter(i -> checkBox.isEnabled()) 

// Approach 2 
Observable.interval(1, TimeUnit.SECONDS) 
    .withLatestFrom(
    RxCompoundButton.checkedChanges(checkBox), 
    (isChecked, intervalCounter) -> { 
      if (!isChecked) { 
       return Optional.empty(); 
      } else { 
       return Optional.of(intervalCounter); 
      } 
    }).filter(Optional::isPresent).map(Optional::get) 
関連する問題