【问题标题】:Running operation on background context in Android在 Android 中的后台上下文上运行操作
【发布时间】:2021-06-13 18:54:06
【问题描述】:

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

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

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()

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

【问题讨论】:

  • 为什么不用协程?

标签: android multithreading kotlin background


【解决方案1】:

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

要正确使用您的调度程序,您需要一个 CoroutineScope 用于 launch 一个协程,并且在该协程中,您可以使用 withContext(threadContext) 来完成您的后台工作。在 Android 上,您应该很少需要创建自己的 CoroutineScope,因为活动、片段和视图模型都为您提供了一个已经在其生命周期范围内的对象。

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

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

【讨论】:

  • 非常感谢您的解释 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
相关资源
最近更新 更多