主题的多个订阅者。订阅时打开,否则关闭

时间:2014-12-30 08:01:45

标签: java rx-java

我一直试图找到一种优雅的方式来做到这一点,但到目前为止尚无法实现。有很多次我想要一个这样的设计模式,但是还没有找到足够的东西。

以下是一个用例:在Android中,您可以获得GPS位置更新。保持GPS虽然昂贵。让GPS运行成本很高,特别是当您没有对位置更新做任何事情时。我希望有一个可以有多个订阅的Subject / Observable,当它获得1个订阅时,它会获得并保持GPS启动并开始流式位置更新。当所有订阅都取消订阅时,它会关闭GPS。

实现这种一般行为的好方法是什么?

2 个答案:

答案 0 :(得分:2)

您可以使用share运算符,它基本上等同于publish().refcount()。我没有测试过以确保它可以恢复,但代码似乎表明它可以。基本上,当有一个订阅者时,它“连接”以启动输出,该订阅者仅由一个订阅支持。同时它引用计算任何其他子订阅者,当它降至零时,它取消订阅支持订阅。这意味着您可以在调用share运算符之前挂接onSubscribe / onUnsubscribe ,并使用GPS或其他任何需要抽取数据的内容执行您需要的操作。 Pseudo-Java领先:

public class GPSLocationManager {
    private final Observable<Location> locations;

    public GPSLocationManager() {
        locations = getMagicalGPSLocationObservable()
            .doOnSubscribe(() -> turnOnGps())
            .doOnUnsubscribe(() -> turnOffGps())
            .share();
    }

    public Observable<Location> getLocations() {
        return locations;
    }

}

就像我说的那样,打开的问号似乎是在你下降到0后,你是否可以重启连接。我相信答案是肯定的,但我并不积极。

答案 1 :(得分:0)

可以是一种引用计数形式,作为代理实现。 见the proxy pattern

基本上,您包装要公开的服务,如果引用计数大于0/0,则打开/关闭代理中的实际服务。

因此,您的代理会跟踪其打开的次数。 (所有打开的连接到它的源)。如果引用计数为0则关闭GPS。

这意味着您无法拥有真正的代理,因为最终用户必须调用open / close。 不要使用finalize,因为这会导致不可预见的后果。 (不要相信垃圾收集器的时间参考计数器)。

如果你必须纯粹使用GPS接口(无法通过open / close / addRef / removeRef扩展它),那么你也可以猜测它,并让每个代理保持一个“最后一次”#c;计时器,当它过期时,关闭/丢弃它的引用计数,并在激活时再次增加引用计数)但是这将永远是一个交易(有时你的代码会错误地猜测它没有被使用)

无论如何,无论如何,使用的模式都是我怀疑的代理。