android - 将听众变成 kotlin 协程通道
问题描述
我有几个函数想用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
。
推荐阅读
- r - R中的饼图,其中切片表示数据集列中值的频率
- microsoft-graph-api - Outlook 如何与在 Google 中创建的事件同步?
- python - 保存 Python 工具(如类和函数)存储库的正确方法是什么?
- mongodb - 当 mongo shell 正在运行并且 mongod 的状态显示为活动时,Mongo 服务器未运行
- angular - 嵌套命名的多条路由的问题
- reactjs - 转换 TypeOrm 实体以响应友好的 Typescript DTO
- angular - 名称模型的 Angular 良好实践
- node.js - 意图处理程序失败并出现错误:未定义缓冲区
- java - 我是否被迫在 Hibernate 查询中使用别名?
- android - Android中的JSON数组和对象