【问题标题】:How to know if observable emit was a cached BehaviourSubject value?如何知道 observable emit 是否是缓存的 BehaviourSubject 值?
【发布时间】:2017-10-20 18:15:42
【问题描述】:

我使用 BehaviourRelay 作为源 observable,我喜欢它会在订阅时发出最后一个缓存的值,所以我不需要手动调用 showPlayingState(mPlayStateManager.getCurrentState())。

但是,当我想对订阅中的动画做出反应时,这会带来一个问题,因为我不想在这个缓存的发出时运行动画,当我订阅 onCreate 时会发出,UI 应该只是跳转到不动画的状态它。动画应该只在“新鲜”发射的情况下运行

这至少对我来说是一个相当常见的用例,但我无法在 rx 中弄清楚它

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

【问题讨论】:

    标签: android rx-java behaviorsubject


    【解决方案1】:

    如果我正确理解您的问题,如果 playState() 是较旧的信息,您不想执行动画,但仅在它切换状态时才执行。换句话说,在onCreate() 的初始调用中,您不想做动画,但如果值发生变化,则想做动画。

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

    通过使用UNKNOWN 值重新定义播放状态,简化了启动条件。只需为首次使用后重置的第一个过渡添加一个标志即可实现您的既定目标。

    【讨论】:

    • 是的,但主题可以开始为空,没有缓存的值
    • 然后呢?您的问题没有描述这种情况下的行为。代码显示您在等待值被定义。
    • 什么意思?行为中继没有初始默认值,因此可以为空,订阅时不会缓存发射,第一次“新鲜”发射将被错误地对待。顺便说一句,这取决于它是一个你不应该知道的行为中继,因此是 hide(),我有没有办法可以在发出的数据中对其进行编码?
    • 让我们稍微备份一下设计。为什么playState() observable 在设置之前是未定义的?它可能应该总是被定义,可能以UNKNOWN 作为它的初始状态。
    • 好的,那行得通。但我仍然不喜欢你必须知道它的行为这一事实
    猜你喜欢
    • 1970-01-01
    • 2017-04-19
    • 1970-01-01
    • 2019-05-24
    • 2012-02-17
    • 1970-01-01
    • 2019-10-11
    • 2012-07-06
    • 1970-01-01
    相关资源
    最近更新 更多