Оператор подавления дребезга Android Rx

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

Внизу у меня есть пейджер, и я хотел бы вызвать веб-службу при прокрутке страницы, избегая многих бесполезных вызовов.

Итак, я обнаружил, что оператор «debounce» — это то, что я ищу, но в моем случае он не работает, и веб-служба вызывается каждый раз.

v.pager.addOnScrollListener(object : RecyclerView.OnScrollListener() {

    override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
        super.onScrollStateChanged(recyclerView, newState)
        if (newState == RecyclerView.SCROLL_STATE_IDLE) {

            val itemPosition : Int = layoutManager.findFirstCompletelyVisibleItemPosition();

            Observable.just(itemPosition).debounce(1500, TimeUnit.MILLISECONDS).map {
                  retrieveUserDetail(userList[itemPosition])
            }.observeOn(AndroidSchedulers.mainThread()).subscribe()

         }
    }
})

Что не так с этим кодом?


person Stack Diego    schedule 06.12.2018    source источник
comment
Объявите свой Observable вне области обратного вызова слушателя.   -  person PPartisan    schedule 06.12.2018
comment
Я попытался объявить это вне слушателя и просто подписаться внутри него, но безуспешно.   -  person Stack Diego    schedule 06.12.2018
comment
Debounce добавляет задержку к испускаемым элементам Observable, но не препятствует подписке. Вы также каждый раз создаете новую наблюдаемую из itemPosition и подписываетесь на нее сразу после этого.   -  person Mauro Curbelo    schedule 06.12.2018
comment
@MauroCurbelo это имеет смысл, так как мне отредактировать код?   -  person Stack Diego    schedule 06.12.2018
comment
Это хороший вопрос, и мне никогда не приходилось сталкиваться с этой ситуацией, поэтому я не уверен, есть ли какой-то особый способ RxJava. Во-первых, объявите свой наблюдаемый объект вне области видимости, чтобы каждый раз он не был новым наблюдаемым. Во-вторых, своего рода хакерское решение будет состоять в том, чтобы сохранить логическое значение и предотвратить подписку до тех пор, пока предыдущая полностью не завершится.   -  person Mauro Curbelo    schedule 06.12.2018
comment
Я не очень хорошо разбираюсь в Kotlin, но процесс должен быть таким: (1) вы определяете какой-то эмиттер как переменную экземпляра и вызываете onNext() внутри вашего прокрутки. Самым простым, вероятно, будет Subject (т.е. PublishSubject). Затем (2) в другом месте подпишитесь на ваш эмиттер с остальной частью вашей цепочки, включая debounce.   -  person PPartisan    schedule 06.12.2018


Ответы (1)


Как объяснили Stack Diego и PPartisan в комментариях, вы должны создать наблюдаемое за пределами слушателя и подписаться на него один раз. Поскольку каждый наблюдаемый объект испускает только один элемент, debounce не окажет никакого влияния.

Ваш код, вероятно, будет выглядеть примерно так:

Объявите свою тему как переменную-член.

val subject: PublishSubject<Int> = PublishSubject.create()

Подпишитесь на субъект вне прослушивателя (вы можете сделать это в onResume или onStart, если вы планируете удалять наблюдаемое, когда действие приостановлено)

subject
    .debounce(1500, TimeUnit.MILLISECONDS)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe { retrieveUserDetail(userList[itemPosition]) }

А затем внутри вашего прослушивателя прокрутки создайте новый элемент, когда вызывается onScrollStateChanged()

v.pager.addOnScrollListener(object : RecyclerView.OnScrollListener() {

    override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
        super.onScrollStateChanged(recyclerView, newState)
        if (newState == RecyclerView.SCROLL_STATE_IDLE) {
            val itemPosition : Int = layoutManager.findFirstCompletelyVisibleItemPosition()
            subject.onNext(itemPosition)
         }
    }
})
person Damon Baker    schedule 07.12.2018
comment
И это просто работает ;) Насколько я понимаю, debounce работает с выбросами одной и той же подписки, но я каждый раз создавал новую подписку. onNext() сделал свое дело, спасибо - person Stack Diego; 07.12.2018