简体   繁体   中英

Emit items in RxJava in an interval which depends on the emitted item itself

In RxJava for Android, I want to emit items in an interval which depends on the item itself: In the Observable, I pull an item from a queue, process it and emit it. Dependent on the type of the item, I want to adjust after what time the next item shall be emitted (slow down or speed up the interval).

The following code, as proposed by @a.bertucci here Emit objects for drawing in the UI in a regular interval using RxJava on Android demonstrates how to emit items in a regular interval.

private void drawPath(final String chars) {
    Observable.zip(
        Observable.create(new Observable.OnSubscribe<Path>() {
            // all the drawing stuff here
            ...
        }),
        Observable.timer(0, 50, TimeUnit.MILLISECONDS),
        new Func2<Path, Long, Path>() {
            @Override
            public Path call(Path path, Long aLong) {
                return path;
            }
        }
    )
    .subscribeOn(Schedulers.newThread())
    .observeOn(AndroidSchedulers.mainThread())
    ...
}

My question now is, if it is possible at all to modify the emission frequency while the observable is emitting, and what's the preferred implementation using RxJava.

You can use

 public final <U, V> Observable<T> delay(
            Func0<? extends Observable<U>> subscriptionDelay,
            Func1<? super T, ? extends Observable<V>> itemDelay)

or

public final <U> Observable<T> delay(Func1<? super T, ? extends Observable<U>> itemDelay)

You can use itemDelay to control the speed.

According to your comment, I think you should build a new operator for doing this.

This operator will take a function which compute the delay to apply to emit your next item

 Observable.range(1, 1000).lift(new ConfigurableDelay((item) -> 3 SECONDS)
                          .subscribe();

You can try something like this :

public class ConfDelay {

public static void main(String[] args) {
    Observable.range(1, 1000).lift(new ConfigurableDelay(ConfDelay::delayPerItem, Schedulers.immediate()))
            .map((i) -> "|")
            .subscribe(System.out::print);
}


public static TimeConf delayPerItem(Object item) {
    long value = ((Integer) item).longValue();
    return new TimeConf(value * value, TimeUnit.MILLISECONDS);
}

private static class TimeConf {
    private final long time;
    private final TimeUnit unit;

    private TimeConf(final long time, final TimeUnit unit) {
        this.time = time;
        this.unit = unit;
    }
}

private static class ConfigurableDelay<T> implements Observable.Operator<T, T> {
    private final Func1<T, TimeConf> itemToTime;
    private final Scheduler scheduler;

    public ConfigurableDelay(final Func1<T, TimeConf> itemToTime) {
        this(itemToTime, Schedulers.computation());
    }

    public ConfigurableDelay(final Func1<T, TimeConf> itemToTime, final Scheduler scheulder) {
        this.itemToTime = itemToTime;
        this.scheduler = scheulder;
    }

    @Override
    public Subscriber<? super T> call(final Subscriber<? super T> subscriber) {
        return new Subscriber<T>(subscriber) {

            private TimeConf nextTime = null;

            @Override
            public void onCompleted() {
                subscriber.onCompleted();
            }

            @Override
            public void onError(final Throwable e) {
                subscriber.onError(e);
            }

            @Override
            public void onNext(final T t) {
                TimeConf previousNextTime = nextTime;
                this.nextTime = itemToTime.call(t);
                if (previousNextTime == null) {
                    subscriber.onNext(t);
                } else {
                    scheduler.createWorker().schedule(() -> subscriber.onNext(t), previousNextTime.time, previousNextTime.unit);
                }
            }
        };
    }
}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM