RxJava递归调用

RxJava递归调用,java,rx-java,rx-android,Java,Rx Java,Rx Android,我发现了一个非常有趣的例子,当您必须根据它发出的数据更改初始的可观察的 我有LocationManager,它提供了一个更新间隔不同的位置 enum LocationUpdateFrequency { HEIGHT, MEDIUM, LOW } interface LocationManager { Observable<Location> getLocationUpdates(LocationUpdateFrequency frequency); Loc

我发现了一个非常有趣的例子,当您必须根据它发出的数据更改初始的
可观察的

我有
LocationManager
,它提供了一个更新间隔不同的位置

enum LocationUpdateFrequency {
    HEIGHT, MEDIUM, LOW
}

interface LocationManager {
    Observable<Location> getLocationUpdates(LocationUpdateFrequency frequency);

    LocationUpdateFrequency calcOptimalFrequency(Location currentLocation, Location prevLocation);
}
枚举位置更新频率{
高度,中等,低
}
接口位置管理器{
可观测的getLocationUpdates(LocationUpdateFrequency频率);
LocationUpdateFrequency calcOptimalFrequency(位置currentLocation,位置prevLocation);
}
所以我想用默认值MEDIUM订阅初始getLocationUpdate,在它生成2个位置之后,我想用新的最佳频率重新订阅

我有一个解决方案,但它使用了可变性:

class LocationState {
    Location currentLocation;
    Location pastLocation;

    boolean isValid() {
        return currentLocation != null && pastLocation != null;
    }
}

class LocationAndFrequency {
    final Location location;
    final LocationUpdateFrequency frequency;

    public LocationAndFrequency(Location location, LocationUpdateFrequency frequency) {
        this.location = location;
        this.frequency = frequency;
    }
}

public Observable<Location> getOptimalLocationUpdates() {
    final LocationManager locationManager = null;
    final LocationState state = new LocationState();
    return Observable.defer(() -> {
                final LocationUpdateFrequency frequency;
                if (state.isValid()) {
                    frequency = locationManager.calcOptimalFrequency(state.currentLocation, state.pastLocation);
                } else {
                    frequency = LocationUpdateFrequency.MEDIUM;
                }

                return locationManager.getLocationUpdates(frequency)
                        .doOnNext(location -> {
                            state.pastLocation = state.currentLocation;
                            state.currentLocation = location;
                        })
                        .map(location -> new LocationAndFrequency(location, frequency));
            })
            .takeUntil(locationAndFrequency -> {
                final LocationUpdateFrequency optimalFrequency =
                        locationManager.calcOptimalFrequency(state.currentLocation, state.pastLocation);
                return locationAndFrequency.frequency != optimalFrequency;
            })
            .map(locationAndFrequency -> locationAndFrequency.location)
            .repeat();
}
类位置状态{
位置当前位置;
地理位置;
布尔值有效(){
返回currentLocation!=null&&pastLocation!=null;
}
}
类别位置和频率{
最终位置;
最终位置更新频率;
公共位置和频率(位置位置、位置更新频率){
这个位置=位置;
这个频率=频率;
}
}
公共可观测的getOptimalLocationUpdates(){
最终位置管理器位置管理器=空;
最终位置状态=新位置状态();
返回可观察。延迟(()->{
最终位置更新频率;
if(state.isValid()){
频率=locationManager.calcOptimalFrequency(state.currentLocation,state.pastLocation);
}否则{
频率=LocationUpdateFrequency.MEDIUM;
}
返回locationManager.GetLocationUpdate(频率)
.doOnNext(位置->{
state.pastLocation=state.currentLocation;
state.currentLocation=位置;
})
.地图(位置->新位置和频率(位置,频率));
})
.takeUntil(位置和频率->{
最终位置更新频率最佳频率=
locationManager.calcOptimalFrequency(state.currentLocation、state.pastLocation);
返回位置和频率.frequency!=最佳频率;
})
.map(locationAndFrequency->locationAndFrequency.location)
.重复();
}

什么是更优雅的解决方案?

getLocationUpdates是在值为on后完成的,还是在值到达时无限推送值?因为repeat,它看起来只会产生值。不,它是不定式,我使用takeUntil和repeat:只要选中的
getLocationUpdates
是最优的,就订阅,然后takeUntil将取消订阅,repeat将订阅新的最优。我希望实现相同的行为,而不具有易变性。你能看看这个impl吗?我正在使用一个主题,但这也可能发生变化:很棒的工作,非常好的示例,如何使用主题实现它。好奇的是,在没有主题和可变变量的情况下实现是可能的吗?好吧,我认为关键是订阅流,并总是在订阅时重播最后一个值。这是一个与主题类似的机械论。你可以看看我的另一个例子:。稍后我会将实现更改为不使用主题,并将其作为答案发布。