首页 > 解决方案 > 使用 dispose 处理程序 rxjava 创建 Observable

问题描述

我们想观察视图大小的变化,我们创建了一个这样的扩展:

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()which 将正确停止订阅:

D/MainFragment:大小更改订阅 $size

但这将继续被调用:

D/MainFragment:ViewTreeObserver 监听器回调。

我们如何以及在哪里删除布局侦听器回调?

标签: androidkotlinrx-java2

解决方案


您需要在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)
        }
    }
}

顺便说一句,RxBinding库已经有一个全局布局监听Observable


推荐阅读