Как 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")}