【发布时间】:2019-02-06 11:02:20
【问题描述】:
我想用几个函数来处理Channels 的管道。主要的是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 中调用。我在做什么错,我该如何调试?
【问题讨论】:
标签: android kotlin kotlinx.coroutines