我们想要观察 View 大小的变化,因此我们创建了一个如下的扩展:
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 changed subscribe on $size
但这将继续被调用:
D/MainFragment: ViewTreeObserver Listener called back.
我们如何以及在哪里删除布局监听器回调?
最佳答案
当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库已经有 global layout listener 的 Observable
关于android - 使用 dispose handler rxjava 创建 Observable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54045153/