在提供给flatmap的rxjava func1对象中使用可变状态是一个好主意吗?

f4t66c6m  于 2021-08-20  发布在  Java
关注(0)|答案(2)|浏览(351)

假设我们需要以一种我们需要知道它之前发射的所有项目的方式来转换一个热可观测对象,以便能够确定下一步发射什么。我发现最方便的解决方案是将func1子类的一个示例传递给flatmap,该子类具有全局状态(例如,Map或以前发出的项列表)。在每次调用中,func1示例都会更新其状态,并在此基础上决定返回什么。
然而,我担心这个解决方案的“精确性”。据我所知,rxjava不适合全局和可变状态,这一解决方案似乎与之相反。另一方面,我确信我的observable实现了observable契约,因此它似乎至少是一个有效的解决方案,如果可以同时调用事件,那么同步将解决问题。
其他可能的解决办法可以是:
创建一个操作符。我想,运算符中的可变状态是允许的。无论如何,我尽量避免使用自定义运算符,因为它们更复杂。
通过扫描传播可观察的历史(在列表或Map中)。我要么对每个发出的项使用相同的对象(列表或Map),这会将一个可变对象引入流中,要么每次都复制整个对象,这会浪费大量性能。
订阅原始可观察对象,修改订阅对象的某些全局状态,并使用此全局状态发出主题(转换后的可观察对象)上的项目。我考虑过这一点,因为当它处理全局状态(和同步)时,它似乎退出了rxjava的范围。
因此,问题是:我是否应该在flatmap中使用具有可变状态的func1实现来根据以前发出的项的历史(顺便说一句,这是可行的)转换项,如果不可行,我应该使用什么替代方案?总的来说,我对处理复杂多变状态的推荐方法感到困惑,而这种复杂多变的状态是转换可观测数据所必需的。
我希望我已经清楚地表达了我的问题。否则,请让我知道,我将尝试用一些特定的问题和代码来描述它。

von4xj4u

von4xj4u1#

通常不建议使用包含可变状态的函数的流,因为可变状态可能在多个应用程序之间共享 Subscriber 这是一个特殊的问题 Observable 链条不过,大多数开发人员通常会进行组装 Observable 在需要的时候使用,很少重复使用 Observable . 例如,按钮单击处理程序将创建 Observable 通过构图,这就衍生出另外两个 Observable s异步从两个不同的位置获取数据,然后订阅本地线程 Observable 例如。单击新按钮将以全新的、独立的方式重复此过程 Observable .
以下是有状态函数问题的解决方案:使有状态位的存在取决于订阅的各个订户: defer() ```
Observable o = Observable.defer(() -> {
return Observable.range(1, 10)
.map(new Func1<Integer, Integer>() {
int sum;
@Override
public Integer call(Integer v) {
sum += v;
return sum;
}
});
});

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

自从 `Func1` 将为每个 `subscribe` 呼叫,它是 `sum` 字段将是每个消费者的本地字段。还请注意 `sum` 返回并自动装箱到不可变的 `Integer` 然后可以在其他线程中自由阅读(想想 `observeOn` )因为它完全脱离了 `sum` 然后继续。
r7xajy2e

r7xajy2e2#

有用的工作通常需要可变状态和共享的可变状态。问题是我们如何将易变性与外界隔离开来。
创建操作符会隐藏操作符示例中的易变性。缺点是,国家对可观察链是私有的。 scan() , reduce()fold() (如果存在的话)将是很好的候选,但它们的实现非常有限,以不明显的方式导出它们的状态,并且还限于它们所连接的可观察链。 SubjectRelay 对象提供了有用的剪切点。
回到基础上来,以线程安全的方式使用私有可访问的数据结构并不是一件坏事。如果您只关心一个观察者链,那么选项1或3中的任何一个都可以很容易地完成这项工作。

相关问题