运行 在 Android 中对后台上下文的操作

Running operation on background context in Android

在一个用 Kotlin 编写的 Android 项目中,我有一个数据结构,我想在单个线程上执行一些操作,因为它们都不是线程安全的,并且执行的操作顺序这很重要。我不想让那个线程成为主线程,因为操作很慢。

我已经尝试通过多种方式创建我的 threadContext:

val threadContext = newFixedThreadPoolContext(1, "Background")
val threadContext = newSingleThreadContext("BioStackContext")
val threadContext = Executors.newSingleThreadExecutor().asCoroutineDispatcher()

每次,当我对其调用 运行 时,我都会得到 isCurrent == true:

threadContext.run {
    val isCurrent = Looper.getMainLooper().isCurrentThread()

但是,如果我对其调用 运行Blocking,我会得到 isCurrent == false:

runBlocking(threadContext) {
    val isCurrent = Looper.getMainLooper().isCurrentThread()

我怎样才能运行它在后台非阻塞?

你调用的run函数是Kotlin的scope function,与协程无关。这是一个可以调用任何东西来创建一个 lambda 的函数,它作为接收者,代码是内联的,所以它 运行 立即在当前线程上。

要正确使用您的调度程序,您需要一个用于 launch 协程的 CoroutineScope,并且在该协程中,您可以使用 withContext(threadContext) 进行后台工作。在 Android 上,您应该很少需要创建自己的 CoroutineScope,因为 Activities、Fragments 和 ViewModel 都为您提供了一个已经确定其生命周期范围的协程范围。

如果您在 Activity 或片段中执行此任务,它将如下所示:

lifecycleScope.launch {
    val result = withContext(threadContext) { // we are in the single thread context in this block
        calculateSomethingTimeConsumingWithObjectOnlyWorkedWithOnMySingleThreadContext()
    }
    // Back on main thread:
    updateUI(result)
}

在 ViewModel 中,您将使用 viewModelScope 而不是 lifecycleScope