Создать Observable с обработчиком утилизации rxjava - PullRequest
0 голосов
/ 04 января 2019

Мы хотим наблюдать за изменениями размера представления и создаем расширение следующим образом:

fun View.layoutSizeObservable(): io.reactivex.Observable<Size> {
    return io.reactivex.Observable.create<Size> { emitter ->
        viewTreeObserver.addOnGlobalLayoutListener {
            Log.d("MainFragment", "ViewTreeObserver Listener called back.")
            if (measuredWidth > 0 && measuredHeight > 0) {
                emitter.onNext(Size(measuredWidth, measuredHeight))
            }
        }
    }
}

И затем мы используем это следующим образом, который работает нормально функционально:

sizeChangedDisposable = titleTextView.layoutSizeObservable().subscribe { size: Size ->
    Log.d("MainFragment", "Size changed subscribe on $size")
}

Однако, одна вещь, которая не совсем то, что мы хотим, это то, что Listener добавляется через addOnGlobalLayoutListener, но никогда не удаляется.

Мы можем позвонить sizeChangedDisposable.dispose(), который правильно остановит подписку:

D / MainFragment: размер изменен, подписаться на $ size

Но это будет продолжать называться:

D / MainFragment: прослушиватель ViewTreeObserver перезвонил.

Как и где мы можем удалить обратный вызов слушателя макета?

1 Ответ

0 голосов
/ 04 января 2019

Вам необходимо удалить слушателя, когда Disposable удален. Чтобы сделать это, установите действие Cancellable для излучателя, удаляющего слушателя.

Пример

fun View.layoutSizeObservable(): io.reactivex.Observable<Size> {
    return io.reactivex.Observable.create<Size> { emitter ->
        val listener = ViewTreeObserver.OnGlobalLayoutListener {
            Log.d("MainFragment", "ViewTreeObserver Listener called back.")
            if (measuredWidth > 0 && measuredHeight > 0) {
                emitter.onNext(Size(measuredWidth, measuredHeight))
            }
        }

        viewTreeObserver.addOnGlobalLayoutListener(listener)

        emitter.setCancellable {
            Log.d("MainFragment", "ViewTreeObserver Listener removed.")
            viewTreeObserver.removeOnGlobalLayoutListener(listener)
        }
    }
}

BTW, RxBinding библиотека уже имеет Observable для прослушивателя глобального макета

...