【问题标题】:Turning listeners into kotlin coroutine channels将听众变成 kotlin 协程通道
【发布时间】: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


    【解决方案1】:

    想通了 - 代码工作正常,但是

    viewTreeObserver.removeOnGlobalLayoutListener(listener)
    

    CoordinatorLayout窃听。

    【讨论】:

      猜你喜欢
      • 2020-04-12
      • 2021-06-18
      • 2021-01-18
      • 1970-01-01
      • 2021-01-24
      • 1970-01-01
      • 2021-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多