【问题标题】:Android Background Job Service on CoroutineScope and Dispatcher.IOCoroutineScope 和 Dispatcher.IO 上的 Android 后台作业服务
【发布时间】:2021-08-22 06:26:25
【问题描述】:

上下文

我正在尝试在 Android 6 中更新几个后台作业。主要目标是使后台作业完成的工作轻松且非 ui 线程阻塞。所以我决定做一些事情:

  • GlobalScope 可能不是一个好主意,因为垂死的线程会终止其他线程。所以 CoroutineScope 会成功的
  • 因为我需要完成 I/O 和网络工作,所以我需要一个专为这些任务设计的线程池。所以我将使用 Dispatchers.IO
  • 绑定的 JobServices 的工作是为“一劳永逸”而设计的。应用程序不在乎 - 所以我会启动作业而不是等待异步输出

代码

我一起设计了以下 JobService 类作为其他人迁移或实现的模板。由于作业被取消,该类将向继承的函数返回 false。

import android.app.job.JobParameters
import android.app.job.JobService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

class TestJobService : JobService() {

    override fun onStartJob(params: JobParameters?): Boolean {
        CoroutineScope(Dispatchers.IO).launch {
            // Fire and Forget
        }
        return false
    }

    override fun onStopJob(params: JobParameters?): Boolean {
        return false
    }
}

问题

如果您想回答,请使用问题的编号。

  1. CoroutineScope 是个好主意吗?
  2. 我从主线程“I/art:注意:结束时间超过纪元:”中收到错误 - 这很令人困惑,可能表明 JobService 在 UI 线程上做了很多工作。但是我没有来自编舞者的错误,如果 UI 出现问题,通常应该是这种情况。
  3. 在 JobService 函数中返回 false 是不是一个坏主意

当前使用的链接

https://medium.com/androiddevelopers/coroutines-on-android-part-i-getting-the-background-3e0e54d20bb https://medium.com/androiddevelopers/coroutines-on-android-part-ii-getting-started-3bff117176dd https://medium.com/androiddevelopers/coroutines-on-android-part-iii-real-work-2ba8a2ec2f45 https://developer.android.com/kotlin/coroutines/coroutines-adv?hl=de#coroutinescope https://kotlinlang.org/docs/coroutines-basics.html#extract-function-refactoring

【问题讨论】:

    标签: android kotlin-coroutines


    【解决方案1】:
    1. 您使用CoroutineScope 所做的唯一事情就是提供IO 调度程序。就目前而言,如果协程中完成的任何工作引发异常,则整个作用域将被取消。如果您从其中启动多个协程,这可能是一个问题。如果您确实关心这一点,您还需要使用SupervisorJobCoroutineScope(Dispatchers.IO) + SupervisorJob() 进行设置。
    2. 如果没有您的实际代码,很难识别该错误的含义。通过快速研究,如果您做了一些只应该在主线程上发生的事情(比如访问某些 Android 组件),那可能会导致该错误。也许检查你的代码是否出现这些情况并将其包装在:
    withContext(Dispatchers.Main) { ... }
    

    但这只是猜测,没有任何实际代码。

    1. docs 表示onStartJob

    只要您的作业正在执行,系统就会代表您的应用持有唤醒锁。此唤醒锁在调用此方法之前获取,直到您调用 jobFinished(android.app.job.JobParameters, boolean) 或系统调用 onStopJob(android.app.job.JobParameters) 通知您的工作后才会释放它正在过早关闭。

    从此方法返回 false 意味着您的工作已经完成。系统对作业的唤醒锁将被释放,并且不会调用 onStopJob(android.app.job.JobParameters)。

    根据wakelock docs

    唤醒锁是一种机制,用于指示您的应用程序需要让设备保持开启状态。

    所以不,从onStartJob 返回false 似乎不正确,因为JobService 将无法正确维护唤醒锁。为了解决这个问题,你应该从这个方法中返回true,并且在协程完成后,你应该调用jobFinished来表明作业已经完成了它的所有工作。

    对于onStopJob,返回值:

    true 向 JobManager 表明您是否要根据在创建作业时提供的重试标准重新安排此作业;或 false 完全结束工作。无论返回的值如何,您的作业都必须停止执行。

    对于这种情况,很难根据您的 sn-p 判断什么是正确的值。您应该能够根据您的用例确定哪个是正确的。在这种方法中,您应该取消之前创建的CoroutineScope。您需要维护对范围的引用才能执行此操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-05
      • 1970-01-01
      • 2013-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-08
      • 1970-01-01
      相关资源
      最近更新 更多