Java `distinctUntilChanged`调用onNext后如何允许同一项
我有一个observable,它不断地发射项目,我需要处理每个项目(处理函数需要一些时间)。因此,在处理一个项目的同时,如果另一个项目发出相同的值, 我可以忽略它,因为同样的工作已经在进行中。但一旦处理了当前项(并称为onNext)。如果以后有同样的要求,我会允许的。 我使用了Java `distinctUntilChanged`调用onNext后如何允许同一项,java,android,rx-java,rx-java2,Java,Android,Rx Java,Rx Java2,我有一个observable,它不断地发射项目,我需要处理每个项目(处理函数需要一些时间)。因此,在处理一个项目的同时,如果另一个项目发出相同的值, 我可以忽略它,因为同样的工作已经在进行中。但一旦处理了当前项(并称为onNext)。如果以后有同样的要求,我会允许的。 我使用了distinctUntildChanged操作符,但我可以看到,即使最后一个项目完成了处理并调用了onNext,如果当前项目与最后一个项目相同,它也不允许 我有一个样本来证明这个问题 我有一节课 class User {
distinctUntildChanged
操作符,但我可以看到,即使最后一个项目完成了处理并调用了onNext
,如果当前项目与最后一个项目相同,它也不允许
我有一个样本来证明这个问题
我有一节课
class User {
String id;
String name;
public User(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object obj) {
User obj1 = (User) obj;
return id.equals(obj1.id);
}
@Override
public String toString() {
return name;
}
}
和一个可观察的(主体)
我发出这样的值
for (int i = 0; i < 20; i++) {
Thread.sleep(1000);
mSubject.onNext(new User(String.valueOf(1), "User " + i)); // all `User`s have same id
}
这里的所有对象都相同(等于方法检查id)。正如您所看到的,第一次处理它花费了user0
,需要5秒钟,在此期间,我可以忽略传入的项目,
但是在此之后,onNext:User 0
我应该允许相同的用户请求,但是distinctunitrichanged
不允许,因为它将最后一个值eqal指定给了相同的用户,我该怎么做?
希望我的问题是清楚的。您可以使用
groupBy()
操作符来区分用户的请求。在每一个可观察的场景中,你可以安排只处理最新的发射
mSubject
.doOnNext(i -> Log.d(TAG, "emitted: " + i))
.observeOn(Schedulers.io())
.groupBy( user -> user )
.flatMap( userObserverable -> userObservable
.onBackpressureDrop()
.map(user -> {
Log.d(TAG, "processing " + user);
Thread.sleep(5000); // processing takes 5 seconds
return user;
})
.subscribe(user -> Log.d(TAG, "onNext: " + user.name));
groupBy()
操作符为每个用户创建一个可观察对象。新用户将为他们创建一个新的可观察对象。每个用户将根据其自身的可观察性排放,如果下游不接受排放,则onBackpressureDrop()
将丢弃用户。因此,您可以通过可流动
和正确的BackpressureStragy
实现这一点。问题是在执行observeOn
时没有设置缓冲区大小。你可以试试这个(尽管是科特林):
输出如下所示:
emitting 0
consuming 0
emitting 1
emitting 2
emitting 3
emitting 4
emitting 5
consuming 5
emitting 6
emitting 7
emitting 8
emitting 9
emitting 10
consuming 10
emitting 11
emitting 12
emitting 13
emitting 14
调用observeOn(调度器)
时,如果我没有弄错的话,背压的默认缓冲区大小应该是128
您可以尝试将上面示例中的缓冲区大小更改为3。你会得到:
emitting 0
consuming 0
emitting 1
...
emitting 5
consuming 1
emitting 6
...
emitting 10
consuming 2
emitting 11
...
emitting 15
consuming 15
emitting 16
...
emitting 20
consuming 16
emitting 21
...
我想你需要使用一个带有下拉式BackPressureStategy的Flowable。我尝试了BackPressureStategy.LATEST
和BackPressureStategy.DROP
,但5秒后,它开始处理用户1
,并且它将处理所有项目,我只需要处理最新的项目。比如在第5秒之后,我只需要最新的值,我可以跳过前面的所有值。我不确定我是否真的理解了这个问题,据我所知,你根本不想distinctUntilChanged
,这听起来像是一个背压策略问题。你能更新你的问题吗?我需要处理每一个最新的用户。如果同一个用户来了,如果已经有一个在进行中,我可以忽略。如果相同的用户在处理旧的相同的用户之后,我应该考虑它。希望它现在清楚了?是的,这样就很清楚了,那么你应该可以用一个FlowTable来实现这一点,因为你的代码没有编译.onBackPressureDrop()
方法在userObservable
onBackPressureDrop()
中不可用,应使用小写字母“p”拼写。但它仍然无法检测到。请看。现在我运行的是IntelliJ而不是android studio,这是唯一的区别。我已经正确地添加了rxJava2依赖项。(这是一个在Intellij中运行的maven项目)Hmmm.GroupedObservable
在RxJava2中没有背压处理,正如您所期望的那样。但是,GroupedFlowable
可以。这意味着您在构建链时必须使用可流动的
而不是可观察的
。现在,我用PublishProcessor
更改了主题
,现在您的代码可以编译,但结果仍然是一样的!!正是我想要的。非常感谢。还有一个问题。第二个参数delayError
实际上是什么意思?我没有从文档中正确地得到它。此外,buffersize是它可以容纳的项目数?或者内存大小(以字节为单位)?因此,delayError
的文档表示“指示onError通知是否可能在调度边界另一侧的onNext通知之前剪切。如果为真,则以onError结尾的序列将按照从上游接收到的相同顺序重新播放”抱歉,我不确定它实际上是做什么的:)缓冲区大小是应用BackPressureStragy之前它将保留的项目数。
mSubject
.doOnNext(i -> Log.d(TAG, "emitted: " + i))
.observeOn(Schedulers.io())
.groupBy( user -> user )
.flatMap( userObserverable -> userObservable
.onBackpressureDrop()
.map(user -> {
Log.d(TAG, "processing " + user);
Thread.sleep(5000); // processing takes 5 seconds
return user;
})
.subscribe(user -> Log.d(TAG, "onNext: " + user.name));
Observable.interval(100, TimeUnit.MILLISECONDS)
.doOnNext { println("emitting $it") }
.toFlowable(BackpressureStrategy.LATEST)
.observeOn(Schedulers.io(), false,1)
.subscribeOn(Schedulers.io())
.subscribe {
println("consuming $it")
Thread.sleep(500)
}
emitting 0
consuming 0
emitting 1
emitting 2
emitting 3
emitting 4
emitting 5
consuming 5
emitting 6
emitting 7
emitting 8
emitting 9
emitting 10
consuming 10
emitting 11
emitting 12
emitting 13
emitting 14
emitting 0
consuming 0
emitting 1
...
emitting 5
consuming 1
emitting 6
...
emitting 10
consuming 2
emitting 11
...
emitting 15
consuming 15
emitting 16
...
emitting 20
consuming 16
emitting 21
...