Как reset a BehaviorSubject

У меня есть BehaviorSubject, который я хотел бы использовать reset - под этим я подразумеваю, что я хочу, чтобы последнее значение не было доступно, как если бы оно только что было создано.

Кажется, я не вижу API для этого, но, полагаю, есть другой способ добиться того же результата?

Мое желаемое поведение заключается в том, что мне нужно выпустить события, и я бы хотел, чтобы подписчики получили последнее событие, когда подписались - если конкретный менеджер находится в состоянии "началось". Но когда этот менеджер "остановлен", последнее событие должно быть недоступным (как если бы оно никогда не начиналось в первую очередь).

Ответ 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);

Ответ 2

Другим методом переключения значения наблюдаемого включения и выключения является использование switchMap() для переключения между фактическим наблюдаемым и пустым.

Предположим, что у вас есть объект-менеджер, и он имеет наблюдаемое, которое показывает его состояние. Тогда,

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

будет выдавать только значения, а manager - в состоянии ON.

Ответ 3

Проблема с ответом @akarnokd состоит в том, что .cast препятствует тому, чтобы YourType был интерфейсом или универсальным типом, таким как List<String>.

Другим вариантом является фильтрация по логическому полю, которое вы можете включать и выключать.

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

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

Если методы вызываются в разных потоках, вы можете использовать AtomicBoolean для флага фильтра.

Ответ 4

Я обнаружил лучшее лучшее решение для некоторых случаев: subject.skiplast(1) он может работать, чтобы "очистить" последнюю позицию в потоке, которая сохраняется из-за поведения BehaviorSubject

Ответ 5

Просто используйте setTimeout так:

setOtpoint(value) {

    this._setOption.next(value);

    // Clear BehaviorSubject after emit value

    setTimeout(() => {
      this._setOption.next(null);
    }, 100);

  }

Ответ 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")}