订阅并取消订阅每个已发布的项目

时间:2015-10-22 19:26:25

标签: java android reactive-programming rx-java rx-android

我正在使用reactive-location lib。

我的用例是我有一个从observable发出的对象流。这些物品可能每隔几个小时发出一次。一旦项目被发出,我想获得一个位置并使用zipWith(据我所知)发出一个包含该位置的对象。

问题是:由于物体每隔几个小时才会被发射一次,我无法保持位置可观察到热,因为它会耗尽电池。

所以我需要以下内容:一旦将对象传递到流中,一旦获得位置就订阅可观察的位置,取消订阅可观察的位置。这必须不断完成。

据我了解,此转换器负责取消订阅

public <T> Observable.Transformer<T, T> takeNextAndUnsubscribe() {
    return new Observable.Transformer<T, T>() {

        @Override
        public Observable<T> call(Observable<T> tObservable) {
            final BehaviorSubject subject = BehaviorSubject.create();
            Observable source = tObservable.doOnNext(new Action1<T>() {
                @Override
                public void call(T t) {
                    subject.onNext(t);
                }
            });
            return Observable
                    .merge(source.takeUntil(subject), subject)
                    .take(1);
        }

    };
}

但是,如果在流中向下发送新对象,我将如何再次订阅?

1 个答案:

答案 0 :(得分:1)

您需要的是将源项目与发布时的当前位置相结合。这里不需要任何花哨的东西。只需在每个源项目上使用flatMap()即可将其与位置相结合。

source.flatMap(item ->
        locationProvider
                .getLastKnownLocation()
                .map(location -> new ItemWithLocation<>(item, location))
);

class ItemWithLocation<T> {
    private final T item;
    private final Location location;

    public ItemWithLocation(T item, Location location) {
        this.item = item;
        this.location = location;
    }

    public T getItem() {
        return item;
    }

    public Location getLocation() {
        return location;
    }
}

编辑:更新了第二个示例。以下内容将订阅位置更新,直到达到特定的准确度,然后将其与源项目合并。这里的关键是使用first()。只要您获得满足您需求的位置,使用它将取消订阅位置提供商。

LocationRequest request = 
        LocationRequest
            .create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(100);

source.flatMap(item ->
        locationProvider
                .getUpdatedLocation(request)
                .first(location -> location.getAccuracy() < 5.0f)
                .map(location -> new ItemWithLocation<>(item, location))
);