Android CoroutineScope 和 Dispatcher.IO 上的后台作业服务

Android Background Job Service on CoroutineScope and Dispatcher.IO

上下文

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

代码

总而言之,我设计了以下 JobService class 作为其他人迁移或实施的模板。由于作业被搁置,class 将 return 对继承的函数为 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 函数中 return 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

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

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

  1. docs表示onStartJob

The system holds a wakelock on behalf of your app as long as your job is executing. This wakelock is acquired before this method is invoked, and is not released until either you call jobFinished(android.app.job.JobParameters, boolean), or after the system invokes onStopJob(android.app.job.JobParameters) to notify your job that it is being shut down prematurely.

Returning false from this method means your job is already finished. The system's wakelock for the job will be released, and onStopJob(android.app.job.JobParameters) will not be invoked.

并且根据 wakelock docs,

A wake lock is a mechanism to indicate that your application needs to have the device stay on.

所以不,从 onStartJob 到 return false 似乎不正确,因为 JobService 不会正确维护唤醒锁。要解决此问题,您应该从该方法 return true 完成协程后,您应该调用 jobFinished 以指示作业已完成其所有工作。

对于 onStopJob,return 值:

true to indicate to the JobManager whether you'd like to reschedule this job based on the retry criteria provided at job creation-time; or false to end the job entirely. Regardless of the value returned, your job must stop executing.

对于这种情况,很难根据您的代码段判断什么是正确的值。您应该能够根据您的用例找出哪个是正确的。在这种方法中,您应该取消之前创建的 CoroutineScope。为此,您需要维护对范围的引用。