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



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

我尝试了多种方式创建我的线程上下文:

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

每次,当我调用run时,我都会得到isCurrent==true:

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

然而,如果我在上面调用runBlocking,我会得到isCurrent==false:

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

如何在后台无阻塞地运行它?

您正在调用的run函数是Kotlin作用域函数,它与协程无关。它是一个可以在任何事情上调用的函数,以创建一个以它为接收器的lambda,并且代码是内联的,因此它可以立即在当前线程上运行。

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

如果你在一个活动或片段中执行这个任务,它看起来像这样:

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

最新更新