web-dev-qa-db-ja.com

Android Rxjavaは変数の変更にサブスクライブします

私はオブザーバーパターンを学んでおり、値が変更されたときに特定の変数を追跡し、いくつかの操作を行うために私のオブザーバブルが欲しいです、私は次のようなことをしました:

public class Test extends MyChildActivity {

   private int VARIABLE_TO_OBSERVE = 0;

   Observable<Integer> mObservable = Observable.just(VARIABLE_TO_OBSERVE);  

   protected void onCreate() {/*onCreate method*/
       super();
       setContentView();
       method();
       changeVariable();
   }

   public void changeVariable() {
       VARIABLE_TO_OBSERVE = 1;
   }

   public void method() {
       mObservable.map(value -> {
            if (value == 1) doMethod2();
            return String.valueOf(value);
       }).subScribe(string -> System.out.println(string));
   }

   public void doMethod2() {/*Do additional operations*/}

}

ただし、doMethod2()は呼び出されません

26
Karate_Dog

人生で魔法はありません。値を更新しても、Observableは通知されません。あなたは自分でそれをしなければなりません。たとえば、PublishSubjectを使用します。

public class Test extends MyChildActivity {

    private int VARIABLE_TO_OBSERVE = 0;

    Subject<Integer> mObservable = PublishSubject.create();  

   protected void onCreate() {/*onCreate method*/
        super();
        setContentView();
        method();
        changeVariable();
    }

    public void changeVariable() {
        VARIABLE_TO_OBSERVE = 1;
        // notify the Observable that the value just change
        mObservable.onNext(VARIABLE_TO_OBSERVE);
    }

   public void method() {
       mObservable.map(value -> {
           if (value == 1) doMethod2();
           return String.valueOf(value);
       }).subScribe(string -> System.out.println(string));
   }

   public void doMethod2() {/*Do additional operations*/}

 }
33
dwursteisen

ここで興味がある場合は、変数クラスのKotlinバージョンを使用すると、変数が変更されるたびにサブスクライバーを更新できます。

class Variable<T>(private val defaultValue: T) {
var value: T = defaultValue
    set(value) {
        field = value
        observable.onNext(value)
    }
val observable = BehaviorSubject.createDefault(value)
}

使用法:

val greeting = Variable("Hello!")
greeting.observable.subscribe { Log.i("RxKotlin", it) }
greeting.value = "Ciao!"
greeting.value = "Hola!"

これは印刷されます:

"Hello!"
"Ciao!"
"Hola!"
36

@dwursteisen何も魔法ではありません、いいえ、しかし、私たちはそれよりも少し魔法を得ることができると思います... ????

この方法でRx BehaviourSubjectを使用する方法は次のとおりです。

_import rx.functions.Action1;
import rx.subjects.BehaviorSubject;    

public class BehaviourSubjectExample {

    public BehaviourSubjectExample() {
        subject.skip(1).subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                System.out.println("The value changed to " + integer );
            }
        });
    }

    public final BehaviorSubject<Integer> subject = BehaviorSubject.create(0);

    public int  getValue()          { return subject.getValue(); }
    public void setValue(int value) { subject.onNext(value);     }
}
_

監視コードに初期値を表示させたい場合は、.skip(1)を削除してください。

変数のバッキングはBehaviourSubjectとともに残り、従来のJava Getter/Setterを介してアクセスできます。これはもちろん簡単な例です。 d書くだけでなく、言い訳にはなりません。

_private int value = 0;

public int  getValue() { return value; }
public void setValue(int value) {
    this.value = value;
    System.out.println("The value changed to " + value );
}
_

...しかし、BehaviourSubjectを使用すると、クラス内の他のRxデータストリームへの変更をブリッジして、より高度な動作を構成できます。

12
Chris Hatton