如何 throttle/debounce seekbar 在 MediaPlayer 应用程序中寻找事件

How to throttle/debounce seekbar seek events in MediaPlayer app

我正在编写一个 MediaPlayer Android 应用程序并想要 throttle/debounce Seekbar 事件。无法找到一个好的解决方案来最小化用户在搜索栏上移动手指时生成的搜索操作的数量。

在不使用额外库的情况下,最简单的解决方案是什么?

我将 post 我的解决方案,其中涉及 RxJava 和 RxBindings 作为帮助他人的答案。

int SEEKBAR_THROTTLE_INTERVAL = 100; //ms
    mSeekBarSubscription = RxSeekBar.userChanges(mSeekBar)
            .doOnNext(new Action1<Integer>() {
                @Override
                public void call(Integer integer) {
                  mUpdateProgressRoutine.stopRoutine();
                }
            })
            .debounce(SEEKBAR_THROTTLE_INTERVAL, TimeUnit.MILLISECONDS)
            .onBackpressureLatest()
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<Integer>() {
                @Override
                public void call(Integer progress) {
                    onProgressChanged(mSeekBar, progress, true);
                }
            });

在这种情况下,我使用了 debounce 并且没有节流。我发现以下类比很有帮助:

Imagine that you go home, enter in the elevator, doors are closing... and suddenly your neighbor appears in the hall and tries to jump on the elevator. Be polite! and open the doors for him: you are debouncing the elevator departure. Consider that the same situation can happen again with a third person, and so on... source

效果是,如果用户在搜索栏上快速移动手指,只有最后一个事件会 "win" 并触发 MediaPlayer 实例上的搜索操作:您不会听到 "scratch-noise"或者浪费性能。

因为我也找不到关于如何在不使用两个不同的 Observable 的情况下订阅所有更改事件的示例,所以我将分享一个示例:

mSeekbarSubscription = RxSeekBar.changeEvents(mSeekBar)
            .ofType(SeekBarProgressChangeEvent.class)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<SeekBarProgressChangeEvent>() {
                @Override
                public void call(SeekBarProgressChangeEvent seekBarChangeEvent) {
                    SeekBar seekBar = seekBarChangeEvent.view();
                    int progress = seekBarChangeEvent.progress();
                    boolean fromUser = seekBarChangeEvent.fromUser();
                    //same as SeekbarListener.onProgressChanged
                }
            });

虽然与问题没有直接关系,但是,如果有人想知道如何订阅 RxSeekBar 的所有三个事件,那你去吧:

科特林:

        RxSeekBar.changeEvents(seekbar)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { seekBarChangeEvent ->
                when (seekBarChangeEvent) {
                    is SeekBarProgressChangeEvent -> Log.d(TAG, "on Progress : " + seekBarChangeEvent.progress())
                    is SeekBarStartChangeEvent -> Log.d(TAG, "on Start : ")
                    is SeekBarStopChangeEvent -> Log.d(TAG, "on Stop : ")
                }
            }

Java:

    RxSeekBar.changeEvents(seekbar)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(seekBarChangeEvent -> {
                if (seekBarChangeEvent instanceof SeekBarProgressChangeEvent)
                {
                    SeekBarProgressChangeEvent seekBarProgressChangeEvent = (SeekBarProgressChangeEvent) seekBarChangeEvent;
                    Log.d(TAG, "on Progress : " + seekBarProgressChangeEvent.progress());
                }
                else if (seekBarChangeEvent instanceof SeekBarStartChangeEvent)
                {
                    Log.d(TAG, "on Start : " );
                }
                if (seekBarChangeEvent instanceof SeekBarStopChangeEvent)
                {
                    Log.d(TAG, "on Stop : " );
                }
            });