【问题标题】:Android how organise coroutines in elegant way?Android 如何以优雅的方式组织协程?
【发布时间】:2019-02-17 14:55:53
【问题描述】:

以优雅的方式组织应用程序协程的最佳方式是什么?我明白了,这个问题似乎很奇怪。让我展示一下Executors

的例子

创建一个对象 AppExecutors.kt

object AppExecutors {

    private val main: Executor = MainThreadExecutor()
    private val util: Executor = Executors.newFixedThreadPool(3)

    fun main(f: () -> Unit) {
        main.execute(f)
    }

    fun util(f: () -> Unit) {
        util.execute(f)
    }

    class MainThreadExecutor : Executor {
        private val mainThreadHandler = Handler(Looper.getMainLooper())
        override fun execute(command: Runnable?) {
            mainThreadHandler.post(command)
        }
    }
}

现在,我们可以使用它了。简单、最少的代码等

val exe = AppExecutors
exe.util {
    val first = calculateFirst()
    val second = calculateSecond()
    val str = ("first = $first | second = $second")
    exe.main {
        Toast.makeText(activity, "Executors $str", Toast.LENGTH_LONG).show()
    }
}

现在,我尝试在协程上使用这种方法 AppCoRoutines.kt

object AppCoRoutines{
    private val uiContext: CoroutineContext = Dispatchers.Main
    private val ioContext: CoroutineContext = Dispatchers.IO
    private val networkContext: CoroutineContext = Executors.newFixedThreadPool(3).asCoroutineDispatcher()
    private val singleContext: CoroutineContext = Executors.newSingleThreadExecutor().asCoroutineDispatcher()

    val ui: CoroutineScope = CoroutineScope(uiContext)
    val io: CoroutineScope = CoroutineScope(ioContext)
    val net: CoroutineScope = CoroutineScope(networkContext)
    val single: CoroutineScope = CoroutineScope(singleContext)
}

现在,使用这个:

val coRout = AppCoRoutines
coRout.ui.launch {
    val str: String = withContext(coRout.net.coroutineContext){
        val first = async { calculateFirst() }
        val second = async { calculateSecond() }
        ("first = $first | second = $second")
    }
    Toast.makeText(activity, "CoRoutine $str", Toast.LENGTH_LONG).show()
}

一点也不优雅。也许有人可以提出更简单的方法?我现在在这方面不太擅长,所以我只使用协程来完成简单的任务。

提前谢谢你!

【问题讨论】:

  • 为什么要创建自己的执行器?协程开箱即用。 GlobalScope.launch(Dispatchers.Main) { val str: String = withContext(Dispatchers.IO) { val first = async { calculateFirst() } val second = async { calculateSecond() } ("first = $first | second = $second ") } Toast.makeText(activity, "CoRoutine $str", Toast.LENGTH_LONG).show() }
  • 您好!谢谢您的回复!问题不在于我为什么要这样做,而在于我如何以简单的方式做到这一点,正如我在 Executors 示例中展示的那样。谢谢!

标签: android kotlin kotlinx.coroutines


【解决方案1】:

您需要在协程的调用站点(您想使用协程的任何地方,例如当前实现中的coRout.ui.launch)扩展CoroutineScope。这样,您不必在任何地方都编写和重复coRout.ui.launch,而且您可以避免当前代码中的内存泄漏(因为您的协程可以在您的调用对象想要被销毁时仍然存在)

例如,如果你在一个类中,你可以让你的类扩展CoroutineScope,如下所示:

class SomeClass: CoroutineScope {
    val job = Job()
    override val coroutineContext: CoroutineContext
        get() = job + coRout.net.coroutineContext
}

在这个类中,您可以使用launchwithContext 轻松处理您的协程。当你知道你的类正在被销毁时,你也可以cancel()job 对象(如onDestory 用于android活动),以便取消该类的所有协程。

【讨论】:

    猜你喜欢
    • 2011-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-21
    • 2013-04-23
    • 1970-01-01
    • 2015-06-10
    • 2015-10-29
    相关资源
    最近更新 更多