2017-10-20 7 views
0

Ich benutze ein BehaviourRelay als Quelle beobachtbar, ich mag, dass es den letzten zwischengespeicherten Wert beim Abonnement ausgibt, so dass ich nicht manuell den showPlayingState aufrufen muss (mPlayStateManager.getCurrentState()).Wie kann man wissen, ob die beobachtbare Emission ein zwischengespeicherter BehaviourSubject-Wert war?

Allerdings stellt dies ein Problem, wenn ich mit einer Animation in subscribe reagieren möchte, da ich keine Animation auf diese zwischengespeicherte emittieren möchte, die beim Anmelden in onCreate gesendet wird, UI sollte einfach in den Zustand nicht animieren springen zu ihm. Animation sollte nur im Fall eines „frischen“ emittieren

Dies ist ein ziemlich häufiger Anwendungsfall atleast für mich laufen, aber ich bin Mühe, es in rx herauszufinden

class Activity { 

    PlayStateManager mPlayStateManager; 
    Button mButton; 

    void onCreate(SavedinstanceState state) { 
     mPlayStateManager.playState() 
     .subscribe(state -> { 
      switch(state) { 
      case PlayState.PLAYING: 
       showPlayingState(true, ???); 
       break; 
      case PlayState.PAUSED: 
       showPlayingState(false, ???); 
       break; 
      } 
     } 
    } 

    void showPlayingState(boolean isPlay, boolean animate) { 
    if(!animate) { 
     mButton.setText(isPlay ? "Playing" : "Paused"); 
    } else { 
     mButton.animate() 
      .rotate(360) 
      .onAnimationEnd(() -> { 
       mButton.setText(isPlay ? "Playing" : "Paused"); 
      }) 
     } 
    } 
} 


class PlayStateManager { 

    BehaviourRelay<PlayState> mSubject = new BehaviourRelay(); 

    public void set(PlayState state) { 
     mSubject.accept(state); 
    } 

    public Observable<PlayState> playState() { 
     return mSubject.hide(); 
    } 
} 

Antwort

0

Wenn ich Ihre Frage richtig verstanden , Sie möchten die Animation nicht ausführen, wenn die playState() ältere Information ist, aber nur wenn sie den Status wechselt. Mit anderen Worten, beim ersten Aufruf von onCreate() möchten Sie die Animation nicht ausführen, möchten jedoch die Animation ausführen, wenn sich der Wert ändert.

enum PlayStateExpanded { 
    UNKNOWN, 
    PLAYING, 
    PAUSED 
} 

class PlayStateManager { 

    BehaviourRelay<PlayStateExpanded> mSubject = 
     new BehaviourRelay(PlayStateExpanded.UNKNOWN); 

    public void set(PlayState state) { 
     mSubject.accept(
      state == PlayState.PLAYING ? PlayStateExpanded.PLAYING 
             : PlayStateExpanded.PAUSED); 
    } 

    public Observable<PlayStateExpanded> playState() { 
     return mSubject.hide(); 
    } 
} 

void onCreate(SavedinstanceState state) { 
    AtomicBoolean firstTime = new AtomicBoolean(true); // note first time 
    mPlayStateManager.playState() 
    .subscribe(state -> { 
     switch(state) { 
     case PlayStateExpanded.PLAYING: 
      showPlayingState(true, firstTime.get()); 
      break; 
     case PlayStateExpanded.PAUSED: 
      showPlayingState(true, firstTime.get()); 
      break; 
     } 
     firstTime.set(false); // no longer first time 
    } 
} 

durch das Spiel Zustand mit einem UNKNOWN Wert neu zu definieren, die Startbedingung vereinfacht. Das Hinzufügen eines Flags für den ersten Übergang, der nach der ersten Verwendung zurückgesetzt wird, führt zu Ihrem angegebenen Ziel.

+0

ja, aber Betreff kann leer beginnen, ohne den zwischengespeicherten Wert – urSus

+0

Und? Deine Frage hat das Verhalten in einem solchen Fall nicht beschrieben. Der Code zeigte, dass Sie darauf gewartet haben, dass der Wert definiert wurde. –

+0

was meinst du? behaviorrelayhat keinen initialen Standardwert, thereforce kann leer sein, reforce wird bei der subskribierung nicht zwischengespeichert ausgegeben und erste "frische" emit werden als solche falsch behandelt. BTW das ist abhängig von der Tatsache, dass es eine Verhaltensrelay, die Sie nicht wissen sollten, daher die hide(), gibt es wie ich es in den emittierten Daten vielleicht kodieren kann? – urSus

Verwandte Themen