【问题标题】:How to reset a BehaviorSubject如何重置 BehaviorSubject
【发布时间】:2018-02-08 03:37:05
【问题描述】:

我有一个想要重置的BehaviorSubject - 我的意思是我希望最新的值不可用,就像它刚刚创建一样。

我似乎没有看到可以执行此操作的 API,但我想还有另一种方法可以达到相同的结果吗?

我想要的行为是我需要发出事件,并且我希望订阅者在订阅时获得最新事件 - 如果特定管理器处于“已启动”状态。但是当这个经理被“停止”时,最新的事件不应该是可用的(就像它从一开始就没有启动一样)。

【问题讨论】:

  • 有了一个 BehaviorSubject,当它刚被创建时就有下一个可用的值,这就是它的全部意义(以及为什么你必须在创建它时提供该值)。
  • @jonrsharpe 但是您不必在创建它时提供它! reactivex.io/RxJava/2.x/javadoc/io/reactivex/subjects/…
  • 很奇怪,它在 RxJS 版本中没有 (github.com/Reactive-Extensions/RxJS/blob/master/doc/api/…) - 如果您不想提供初始值,为什么不使用 ReplaySubject 代替呢?
  • 我的印象是 BehaviorSubject 相当于大小为 1 的 ReplaySubject。但这根本不能回答我的问题 :)
  • 我认为答案是:你不能。但我最初也被一个空洞的行为主体的前提弄糊涂了!

标签: stream rx-java reactive-programming rx-java2


【解决方案1】:

我假设你想清除BehaviorSubject(因为否则不要调用onComplete)。这不受支持,但您可以通过使用被消费者忽略的当前值来实现类似的效果:

public static final Object EMPTY = new Object();

BehaviorSubject<Object> subject = BehaviorSubject.createDefault(EMPTY);

Observable<YourType> obs = subject.filter(v -> v != EMPTY).cast(YourType.class);

obs.subscribe(System.out::println);

// send normal data
subject.onNext(1);
subject.onNext(2);

// clear the subject
subject.onNext(EMPTY);

// this should not print anything
obs.subscribe(System.out::println);

【讨论】:

  • 我不能使用这个解决方案,但它也有助于解决我的问题:如果你使用像 List 这样的泛型类,例如,演员是不可能的......使用空的默认对象在这种情况下,使用v -&gt; !v.equals(EMPTY) 的具体类和过滤器以及移除演员应该会有所帮助。
【解决方案2】:

另一种打开和关闭可观察值的方法是使用switchMap() 在实际可观察​​值和空值之间切换。

假设您有一个 manager 对象,并且它有一个显示其状态的 observable。那么,

subjectObservable = manager.getStateObservable()
  .switchMap( state -> state == ON ? subject : Observable.never() );

只会在manager 处于ON 状态时发出值。

【讨论】:

  • 有趣!谢谢。
  • 能否补充一下 manager 是如何维护 stateObservable 的?
  • stateObservable 由管理器使用其拥有的任何状态信息进行维护。原始问题的状态为 BehaviorSubject,但可以使用任何可观察到的来源。
【解决方案3】:

我为某些情况找到了更好的解决方案,并且是:

subject.skiplast(1)

它可以清理由于BehaviorSubject“行为”而保留的流上的最后一个位置

【讨论】:

  • 这会返回一个 Observable 虽然不是一个主题
【解决方案4】:

@akarnokd 回答的一个问题是 .cast 阻止 YourType 成为接口或泛型类型,例如 List&lt;String&gt;。

另一个选项是过滤一个可以打开和关闭的布尔字段。

    private BehaviorSubject<PandoraApp> subject = BehaviorSubject.create();
    private boolean enabled = true;

    Observable<PandoraApp> observable = subject.filter(v -> enabled);

如果在不同的线程上调用方法,您可以使用 AtomicBoolean 作为过滤器标志。

【讨论】:

    【解决方案5】:

    只需像这样使用 setTimeout:

    setOtpoint(value) {
    
        this._setOption.next(value);
    
        // Clear BehaviorSubject after emit value
    
        setTimeout(() => {
          this._setOption.next(null);
        }, 100);
    
      }
    

    【讨论】:

    • 我试过上面的代码它的工作,但再次登录后_setOption是获得空白值和刷新后收到值
    【解决方案6】:

    这是我的库:​​

    implementation "com.github.kolyall:rxjava2-empty:1.0.36"

    例子:

    
    private val myBehaviorSubject = BehaviorSubjectOptional.createOptional<MyItem?>()
    
    errorBehaviorSubject.toObservable()
    .subscribe{ item-> Log.d("onNext1", "item = $item")}
    
    var item:MyItem? = MyItem()
    myBehaviorSubject.onNextOptional(item)
    
    //For reset:
    myBehaviorSubject.clear()
    //OR
    item = null
    myBehaviorSubject.onNextOptional(item)
    
    
    errorBehaviorSubject.toObservable()
    .subscribe{ item-> Log.d("onNext2", "item = $item")}
    

    【讨论】:

      猜你喜欢
      • 2023-03-26
      • 2019-06-19
      • 1970-01-01
      • 2022-12-03
      • 1970-01-01
      • 1970-01-01
      • 2023-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多