带有协程中缀的构建器模式

Builder pattern with infix for Coroutines

我正在尝试编写 class 以在不同的协程上下文中轻松链接代码 运行。

理想情况下,我想这样使用它:

        io {
            // Run IO code that returns an object (nullable)
        } ui { ioResult->
            // Run UI code using the returned object (non-nullable)
        } ifNull {
            // Run UI code when the returned object is null
        }

我目前的工作方式如下:

        GlobalScope.launch {
            CoroutineLinker(null).io {
                // Run IO code
            } ui { ioResult ->
                ioResult?.also {
                    // Run UI code after null check
                } ?: run {
                    // Run UI code when null
                }
            } ifNull {
                // Redundant block
            }
        }

如您所见,还有很多工作要做,但我被卡住了,所以我与您分享:

    class CoroutineLinker<T> (
        private val value: T?
    ) {

        suspend infix fun <K> io (block: suspend () -> K?): CoroutineLinker<K?> {
            return withContext(Dispatchers.IO) {
                CoroutineLinker(block())
            }
        }

        suspend infix fun ui (block: suspend (value: T) -> Unit): CoroutineLinker<T> {
            return withContext(Dispatchers.Main) {

                if (value != null ) {
                    block(value)
                }

                this@CoroutineLinker
            }
        }

        suspend infix fun ifNull (block: suspend () -> Unit) {
            return withContext(Dispatchers.Main) {
                if (value == null) {
                    block()
                }
            }
        }
    }

欢迎任何意见! :)

我认为这会满足您的需求:

suspend fun <K : Any> io (block: suspend () -> K?) = CoroutineLinker(null).io(block)

class CoroutineLinker<T : Any> (
    private val value: T?
) {

    suspend infix fun <K : Any> io (block: suspend () -> K?): CoroutineLinker<K> {
        return withContext(Dispatchers.IO) {
            CoroutineLinker(block())
        }
    }

    suspend infix fun ui (block: suspend (value: T) -> Unit): CoroutineLinker<T> {
        if (value != null ) {
            withContext(Dispatchers.Main) {
                block(value)
            }
        }

        return this
    }

    suspend infix fun ifNull (block: suspend () -> Unit) {
        if (value == null) {
            withContext(Dispatchers.Main) {
                block()
            }
        }
    }
}

我改变了 3 件事:

  • CoroutineLinker 的上限添加到 Any
  • 添加了io功能。
  • 更改了两个函数中 ifwithContext 的顺序 - 这只是优化,不是必需的。