2016-08-03 24 views
13

uczę Wzorzec Obserwator, chcę moje obserwowalne śledzenie pewnej zmiennej, gdy zmienia się jego wartość i zrobić kilka operacji, zrobiłem coś takiego:Android Rxjava subskrybować zmiennej zmian

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*/} 

} 

Ale doMethod2() nie zostanie wywołany

+0

Opuściłem Javę dawno temu. Oto moja myśl. Ponieważ 'VARIABLE_TO_OBSERVE' jest kopiowany do obserwowalnego. Dlatego nie jest przestrzegane. Co powiesz na 'private Integer VARIABLE_TO_OBSERVE = 0;'? – Danh

Odpowiedz

17

Nic nie jest magiczne w życiu: jeśli zaktualizujesz wartość, Twój Observable nie zostanie powiadomiony. Musisz to zrobić sam. Na przykład przy użyciu 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*/} 

} 
+1

Miałem wrażenie, że obserwator natychmiast powiadomi wszystkich swoich subskrybentów za każdym razem, gdy obserwowany obiekt zmieni się. Więc zasadniczo musimy ciągle opowiadać wszystkim subskrybentom, aby słuchali wszelkich zmian? –

+1

Powinieneś ciągle mówić wszystkim swoim Obserwowalnym, że coś się zmienia. Następnie wszyscy subskrybenci zostaną powiadomieni. – dwursteisen

+0

Zastanawiam się, co jeśli chciałbym asynchronicznie zwrócić coś z 'mapy' wewnątrz' metody'. Mam na myśli 'return String.valueOf (value);' jest wywołaniem asynchronicznym. –

7

@dwursteisen Nic nie jest magia, nie, ale myślę, że możemy dostać to trochę więcej magii niż ...

Jak o użyciu Rx BehaviourSubject w ten sposób:

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

Usuń .skip(1), jeśli chcesz, aby kod obserwujący widział wartość początkową.

Zmienny podkład pozostaje z BehaviourSubject i można uzyskać do niego dostęp za pomocą konwencjonalnego programu Java Getter/Setter. To jest przykład zabawki przedmiotu: Jeśli Twój przypadek użycia naprawdę proste to nie byłoby żadnego usprawiedliwienia dla nie tylko pisanie:

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

... ale korzystanie z BehaviourSubject pozwala Ci zmiany mostowych innych danych Rx -streams w twojej klasie do komponowania bardziej zaawansowanych zachowań.