web-dev-qa-db-ja.com

Android)でのRxJavaを使用したキューイングタスク

Androidバックグラウンドデータ同期付きのアプリケーションを開発しています。現在、RxJavaを使用して、定期的にサーバーにデータを投稿しています。それ以外に、ユーザーにデータを提供したいと思います。すぐに同期をトリガーするボタン「強制同期」。Observable.interval()を使用して一定の時間間隔でデータをプッシュする方法と、Observalbe.just()を使用してデータをプッシュする方法を知っています。強制されますが、前の実行中にトリガーされる場合は、それらをキューに入れたいと思います。

したがって、1分が自動同期の間隔である場合の例を見てみましょう。同期が40秒続くとしましょう(簡単にするために、ここでは誇張しすぎています)。万が一、自動がまだ実行されているときにユーザーが「強制」ボタンを押した場合(またはその逆-強制されたものがまだ実行されているときに自動トリガー)、2番目の同期要求をキューに入れて最初のものが終了します。

私はそれにもう少し遠近法を置くかもしれないこのイメージを描きました:

enter image description here

ご覧のとおり、自動がトリガーされ(Observable.interval()によって)、同期中にユーザーが「強制」ボタンを押します。ここで、最初の要求が終了するのを待ってから、強制された要求を再開します。ある時点で、強制リクエストの実行中に、新しい自動リクエストが再度トリガーされ、キューに追加されました。最後のものがキューから終了した後、すべてが停止し、その後、自動が少し後に再びスケジュールされました。

誰かが私にこれを行う方法を正しいオペレーターに教えてくれることを願っています。 Observable.combineLatest()で試しましたが、キューリストが最初にディスパッチされ、キューに新しい同期を追加すると、前の操作が完了したときにキューリストが続行されませんでした。

どんな助けでも大歓迎です、Darko

18
Darko Smoljo

これを行うには、タイマーをボタンクリックObservable/Subjectとマージし、onBackpressureBufferのキューイング効果を使用して、処理をconcatMapします。これにより、時間。

PublishSubject<Long> subject = PublishSubject.create();

Observable<Long> periodic = Observable.interval(1, 1, TimeUnit.SECONDS);

periodic.mergeWith(subject)
.onBackpressureBuffer()
.concatMap(new Func1<Long, Observable<Integer>>() {
    @Override
    public Observable<Integer> call(Long v) {
        // simulates the task to run
        return Observable.just(1)
                .delay(300, TimeUnit.MILLISECONDS);
    }
}
).subscribe(System.out::println, Throwable::printStackTrace);

Thread.sleep(1100);
// user clicks a button
subject.onNext(-1L);

Thread.sleep(800);
13
akarnokd

良い解決策で受け入れられた答えがありますが、スケジューラーとSingleThreadExecutorを使用してこれを行うための別のオプションを共有したいと思います

public static void main(String[] args) throws Exception {
    System.out.println(" init ");
    Observable<Long> numberObservable =
            Observable.interval(700, TimeUnit.MILLISECONDS).take(10);

    final Subject subject = PublishSubject.create();

    Executor executor = Executors.newSingleThreadExecutor();
    Scheduler scheduler = Schedulers.from(executor);
    numberObservable.observeOn(scheduler).subscribe(subject);

    subject.subscribe(onNextFunc("subscriber 1"), onErrorFunc("subscriber 1"),
                    onCompleteFunc("subscriber 1"));

    Thread.sleep(800);
    //simulate action
    executor.execute(new Runnable() {
        @Override
        public void run() {
            subject.onNext(333l);
        }
    });

    Thread.sleep(5000);
}

static Action1<Long> onNextFunc(final String who) {
    return new Action1<Long>() {
        public void call(Long x) {
            System.out.println(who + " got " + x + " :: " + Thread.currentThread().getName()
                    + " -- " + System.currentTimeMillis());
            try {
                //simulate some work
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
}

static Action1<Throwable> onErrorFunc(final String who) {
    return new Action1<Throwable>() {
        public void call(Throwable t) {
            t.printStackTrace();
        }
    };
}

static Action0 onCompleteFunc(final String who) {
    return new Action0() {
        public void call() {
            System.out.println(who + " complete");
        }
    };
}
3
kalin