RxJava - 将冷 Observable 转换为热 Observable

3

我想解决的问题

我正在构建一种MVP(或者你称之为什么都可以),其中视图可以订阅和取消订阅同一个模型。

一开始,视图订阅模型。模型为空,视图不显示任何内容。当调用方法(例如,当用户点击时),会通过网络发出请求。结果将填充模型,模型会通知视图进行更改。

如果另一个视图订阅,它应该被通知模型当前值,而无需通过网络进行任何调用。如果所有视图在请求正在进行时取消订阅,则仍应填充模型,以便另一个视图可以使用。

我的尝试

我正在使用RetrofitRxJava2来进行网络请求,它提供了一个冷的Observable

对于模型,我想构建一个热的Observable,它返回最后发出的项目给任何新的订阅者。如何使热可观察对象从冷的Observable获取其发出的项目?

到目前为止,我可以通过BehaviourSubject实现这一点:

// The same model is provided to all views through a getter
BehaviorSubject<User> model = BehaviorSubject.create();

// Make request
Observable<User> resource = getResourceOverNetwork(3);
resource.subscribe(new Consumer<User>() {
    @Override
    public void accept(@NonNull User user) throws Exception {
        model.onNext(user);
    }
});

这个解决方案感觉不太对,因为我需要手动将来自“冷”Observable的事件转发到BehaviourSubject


1
如果你只想将Retrofit的结果转换为热可观察对象,你可以使用replay(1).autoConnect - Phoenix Wang
使用 replay(1).autoConnect(),我该如何通过网络发出新请求来更新模型,同时传递新参数? - Multicolaure
@LaureC,有两种方法:一种是使用主题中继,因此您可以将您的操作发布到主题中,模型订阅此主题并发出请求。或者创建可观察对象使用发射器。但是,发射器可能不适合MVP模式,但对于RxPM效果很好。 - MightySeal
许多解决方案实际上使用主题,你可以简单地使用 resource.subscribe(model) - Lamorak
@Lamorak,我忘记了Subject也是一个Observer,谢谢你。但是在我的情况下它不起作用,因为resource在发出第一个值后就完成了,这也使得model完成了。再次发出请求将不会使model发出项目,因为它已经完成了。 - Multicolaure
那么RxRelay就是你需要的了 - Lamorak
1个回答

1
感谢您的评论,我成功地使用 RxRelay 实现了所需的内容。
创建模型:
// The same model is provided to all views through a getter
BehaviorRelay<User> model = BehaviorRelay.create();
    
model.subscribe(view);

随时发出请求:
// Make request
Observable<User> resource = getResourceOverNetwork(3);
resource.subscribe(model);
    
// Make a new request
getResourceOverNetwork(4).subscribe(model);

现在更加容易,也更加清洁。非常感谢!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接