Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/207.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
RxJava:找出BehaviorSubject是否为重复值_Java_Android_Reactive Programming_Rx Java - Fatal编程技术网

RxJava:找出BehaviorSubject是否为重复值

RxJava:找出BehaviorSubject是否为重复值,java,android,reactive-programming,rx-java,Java,Android,Reactive Programming,Rx Java,我正在制作一个Android界面,显示从网络获取的一些数据。我想让它显示最新的可用数据,并且永远不会为空(除非还没有提取任何数据),因此我使用BehaviorSubject向订阅者(我的UI)提供最新的可用信息,同时在后台刷新它以更新它 这是可行的,但由于UI中的另一个要求,我现在必须知道发布的结果是否来自网络。(换句话说,我需要知道发布的结果是否是BehaviorSubject的保存项。) 我怎样才能做到这一点?如果我需要将其拆分为多个可观察对象,这很好,只要我能够获取BehaviorSubj

我正在制作一个Android界面,显示从网络获取的一些数据。我想让它显示最新的可用数据,并且永远不会为空(除非还没有提取任何数据),因此我使用BehaviorSubject向订阅者(我的UI)提供最新的可用信息,同时在后台刷新它以更新它

这是可行的,但由于UI中的另一个要求,我现在必须知道发布的结果是否来自网络。(换句话说,我需要知道发布的结果是否是BehaviorSubject的保存项。)


我怎样才能做到这一点?如果我需要将其拆分为多个可观察对象,这很好,只要我能够获取BehaviorSubject的缓存行为(获取最后一个可用结果),同时还能够判断返回的结果是否来自缓存。我能想到的一种黑客方法是检查响应的时间戳是否相对较短,但这实在是太草率了,我宁愿想办法用RxJava来实现这一点。

将行为主体对象的信息存储在数据结构中,并进行良好的查找,如字典。每个值都是一个键,该值是迭代次数


因此,当你看一个特殊的键时,如果你的字典已经包含了它,并且它的值已经是1,那么你知道一个值是一个重复的值。

不包括你的情况吗?Behavior Subject仅在订阅后重复最新的元素。

我相信您想要的是这样的:

private final BehaviorSubject<T> fetched = BehaviorSubject.create();
private final Observable<FirstTime<T>> _fetched = fetched.lift(new Observable.Operator<FirstTime<T>, T>() {
    private AtomicReference<T> last = new AtomicReference<>();
    @Override
    public Subscriber<? super T> call(Subscriber<? super FirstTime<T>> child) {
        return new Subscriber<T>(child) {
            @Override
            public void onCompleted() {
                child.onCompleted();
            }

            @Override
            public void onError(Throwable e) {
                child.onError(e);
            }

            @Override
            public void onNext(T t) {
                if (!Objects.equals(t, last.getAndSet(t))) {
                    child.onNext(FirstTime.yes(t));
                } else {
                    child.onNext(FirstTime.no(t));
                }
            }
        };
    }
});

public Observable<FirstTime<T>> getObservable() {
    return _fetched;
}

public static class FirstTime<T> {
    final boolean isItTheFirstTime;
    final T value;

    public FirstTime(boolean isItTheFirstTime, T value) {
        this.isItTheFirstTime = isItTheFirstTime;
        this.value = value;
    }

    public boolean isItTheFirstTime() {
        return isItTheFirstTime;
    }

    public T getValue() {
        return value;
    }

    public static <T> FirstTime<T> yes(T value) {
        return new FirstTime<>(true, value);
    }

    public static <T> FirstTime<T> no(T value) {
        return new FirstTime<>(false, value);
    }
}
private final BehaviorSubject fetched=BehaviorSubject.create();
private final Observable _fetched=fetched.lift(新的Observable.Operator()){
私有AtomicReference last=新的AtomicReference();
@凌驾

公共订阅者正如你在问题中提到的,这可以通过多个观察来实现。本质上,你有两个观察:“可以观察到新的响应”和“可以观察到缓存的响应”。如果可以“观察到”,您可以将其表示为可观察的。让我们命名第一个
原始
和第二个
重放的

看看这个(JavaScript,但是这些概念可以直接翻译成Java。据我所知,就这些目的而言,没有JavaBin)

这里的总体思路是:用一个字段
“from
注释事件,该字段指示事件的起源。如果它是
原始的
,则它是一个新的响应。如果它是
重放的
,则它是一个缓存响应。可观测的
原始的
将只从以下发出
原始的
,而可观测的
重放的
将只发出
from:“replayed”
。在Java中,我们需要更多的样板文件,因为您需要创建一个类来表示这些带注释的事件。否则,RxJS中的相同运算符可以在RxJava中找到

原始的可观察对象是
publish().refCount()
,因为我们只希望此流的一个实例与所有观察者共享。事实上,在RxJS和Rx.NET中,
share()
publish().refCount()的别名

重放的可观察对象是
replay(1).refCount()
,因为它也像原始对象一样被共享,但是
replay(1)
提供了缓存行为


merged
observative同时包含原始和重播,这是您应该向所有订阅者公开的内容。由于无论何时
original
都会立即发出,因此我们对事件的值使用
distinctUntilChanged
来忽略即时连续。原因是
replay(1).refCount()
此外,合并后的是因为我们希望原始和重播的合并也是所有观察者共享的流的一个单独共享实例。为此,我们将使用
publish().refCount()
,但我们不能失去
replayed
包含的重播效果,因此它是
replay(1).refCount()
,而不是
publish().refCount()

我不太确定您想要实现什么。可能您只想有一个“最新”数据的智能源和第二个数据源,告诉您数据何时刷新

    BehaviorSubject<Integer> dataSubject = BehaviorSubject.create(42); // initial value, "never empty"

    Observable<String> refreshedIndicator = dataSubject.map(data -> "Refreshed!");
    refreshedIndicator.subscribe(System.out::println);

    Observable<Integer> latestActualData = dataSubject.distinctUntilChanged();
    latestActualData.subscribe( data -> System.out.println( "Got new data: " + data));

    // simulation of background activity:
    Observable.interval(1, TimeUnit.SECONDS)
            .limit(100)
            .toBlocking()
            .subscribe(aLong -> dataSubject.onNext(ThreadLocalRandom.current().nextInt(2)));

在整个应用程序的生命周期中设置计数器似乎有点草率:/这是真的,我没有考虑产品@D_Steve595的生命周期,但它应该可以工作。如果我找不到更干净的解决方案,这就必须这样做。正如@MLProgrammer CiM所说,设置将是一个只保存不同值的好解决方案。或者,我会这样做用字典以外的东西找到重复的值再好不过了!我不这么认为,因为我仍然想接收这些项目,我只需要知道它们是否重复。对存储在外部的集合进行筛选。这些正是我要说的!这个集合只会从您的BehaviorSubject对象。这会有什么帮助?对这意味着什么有点困惑。集合仅保留distinct值,因此您不必担心值被重复。否则,使用Rx,distinct将过滤可能重复的项。需要澄清问题…在将第一项提供给BehaviorSubject后,订阅方将始终首先接收缓存版本,然后接收任何新的更新。因此,问题可能是以前是否有人看到过它?事实上,
share()
也是RxJava中
publish().refCount()
的别名。
    BehaviorSubject<Integer> dataSubject = BehaviorSubject.create(42); // initial value, "never empty"

    Observable<String> refreshedIndicator = dataSubject.map(data -> "Refreshed!");
    refreshedIndicator.subscribe(System.out::println);

    Observable<Integer> latestActualData = dataSubject.distinctUntilChanged();
    latestActualData.subscribe( data -> System.out.println( "Got new data: " + data));

    // simulation of background activity:
    Observable.interval(1, TimeUnit.SECONDS)
            .limit(100)
            .toBlocking()
            .subscribe(aLong -> dataSubject.onNext(ThreadLocalRandom.current().nextInt(2)));
Refreshed!
Got new data: 42
Refreshed!
Got new data: 0
Refreshed!
Refreshed!
Refreshed!
Got new data: 1
Refreshed!
Got new data: 0
Refreshed!
Got new data: 1