使用 dispose handler rxjava 创建 Observable

Yuc*_*ong 2 android kotlin rx-java2

我们想要观察视图大小的变化,我们创建一个如下的扩展:

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))
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我们像这样使用它,它的功能很好:

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

然而,有一点并不完全是我们想要的,它是Listener通过 添加的addOnGlobalLayoutListener,但从未被删除。

我们可以调用sizeChangedDisposable.dispose()它将正确停止订阅:

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

但这将继续被调用:

D/MainFragment:回调的ViewTreeObserver监听器。

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

Oma*_*gra 5

您需要在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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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