Установка переменной из цепочки RxJava

Я использую библиотеку ReactiveLocation. По сути, я хочу получить местоположение в течение 4 секунд с достаточной точностью. Если местоположение с достаточной точностью не было получено за это время, но другие местоположения возвращают местоположение с наивысшей точностью.

Как только получено местоположение с достаточной точностью, оно возвращается, и наблюдаемая завершается.

Я опубликую код того, что я пытаюсь. Я мог бы и, вероятно, поступаю неправильно.

LocationRequest request = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setFastestInterval(FASTEST_UPDATE_INTERVAL)
            .setSmallestDisplacement(MIN_DISTANCE_UPDATE_INTERVAL);

    if ( expirationSeconds != null )
        request.setExpirationDuration(TimeUnit.SECONDS.toMillis(expirationSeconds));

    ReactiveLocationProvider locationProvider = new ReactiveLocationProvider(context);
    Observable<Location> observable = locationProvider.getUpdatedLocation(request)
                .doOnNext(new Action1<Location>() {
                    @Override
                    public void call(Location location) {
                        if ( mostAccurateLocation == null )
                            mostAccurateLocation = location;

                        if ( location.getAccuracy() < mostAccurateLocation.getAccuracy() )
                            mostAccurateLocation = location;
                    }
                })
                .filter(new Func1<Location, Boolean>() {
                    @Override
                    public Boolean call(Location location) {
                        return location.getAccuracy() < sufficientAccuracy ;
                    }
                });

    if ( expirationSeconds != null )
        observable = observable.timeout( expirationSeconds, TimeUnit.SECONDS, Observable.just(mostAccurateLocation), backgroundThread );

    return observable.firstOrDefault(mostAccurateLocation)
                     .doOnNext(new Action1<Location>() {
                        @Override
                        public void call(Location location) {
                            lastLocation = location;
                        }
                    });

person StuStirling    schedule 07.12.2016    source источник


Ответы (1)


Хорошо, я нашел проблему. Тайм-аут срабатывал, но, очевидно, наблюдаемое, инициированное тайм-аутом, использовало переменную mostAccurateLocation, как это было во время создания наблюдаемого.

Чтобы исправить это, я использовал шаблон Observable.defer, чтобы он создавал Observable<Location> только при подписке.

    if ( expirationSeconds != null ) {
        Observable<Location> mostAccurateLocationObservable = Observable.defer(new Func0<Observable<Location>>() {
            @Override
            public Observable<Location> call() {
                return Observable.just(mostAccurateLocation);
            }
        });

        observable = observable.timeout( expirationSeconds, TimeUnit.SECONDS, mostAccurateLocationObservable, backgroundThread );
    }
person StuStirling    schedule 07.12.2016