我有我想用做输送管线用Channel
s多种功能。最主要的是globalLayouts
,我在那里创建了框架监听器Channel
:
fun View.globalLayouts(): ReceiveChannel<View> =
Channel<View>().apply {
val view = this@globalLayouts
val listener = ViewTreeObserver.OnGlobalLayoutListener {
offer(view)
}
invokeOnClose {
viewTreeObserver.removeOnGlobalLayoutListener(listener)
}
viewTreeObserver.addOnGlobalLayoutListener(listener)
}
@UseExperimental(InternalCoroutinesApi::class)
fun <E> ReceiveChannel<E>.distinctUntilChanged(context: CoroutineContext = Dispatchers.Unconfined): ReceiveChannel<E> =
GlobalScope.produce(context, onCompletion = consumes()) {
var last: Any? = Any()
consumeEach {
if (it != last) {
send(it)
last = it
}
}
}
fun View.keyboardVisibility(): ReceiveChannel<KeyboardVisibility> {
val rect = Rect()
return globalLayouts()
.map {
getWindowVisibleDisplayFrame(rect)
when (rect.height()) {
height -> KeyboardVisibility.HIDDEN
else -> KeyboardVisibility.SHOWN
}
}
.distinctUntilChanged()
}
我有一个名为CoroutineScope
alive
:
val ControllerLifecycle.alive: CoroutineScope
get() {
val scope = MainScope()
addLifecycleListener(object : Controller.LifecycleListener() {
override fun preDestroyView(controller: Controller, view: View) {
removeLifecycleListener(this)
scope.cancel()
}
})
return scope
}
然后我做的:
alive.launch {
root.keyboardVisibility().consumeEach {
appbar.setExpanded(it == KeyboardVisibility.HIDDEN)
}
}
此代码开始工作得很好,但我得到
kotlinx.coroutines.JobCancellationException: Job was cancelled; job=JobImpl{Cancelled}@811031f
一旦我的alive
范围被破坏。右invokeOnClose
后称为globalLayouts
。我在做什么错了,我该怎么调试呢?
想通了 - 代码工作正常,但
viewTreeObserver.removeOnGlobalLayoutListener(listener)
被窃听的CoordinatorLayout
。