如何从 Service Android 调用挂起函数?
How to call suspend function from Service Android?
如何提供作用域或如何从服务中调用挂起函数Android?
通常,activity 或 viewmodel 为我们提供了范围,我们可以从那里启动暂停,但 Service
中没有类似的东西
您可以创建自己的 CoroutineScope
with a SupervisorJob
,您可以在 onDestroy()
方法中取消。只要您的服务被使用,使用此范围创建的协同程序就会存在。一旦您的服务 onDestroy()
被调用,所有以此范围启动的协程都将被取消。
class YourService : Service() {
private val job = SupervisorJob()
private val scope = CoroutineScope(Dispatchers.IO + job)
...
fun foo() {
scope.launch {
// Call your suspend function
}
}
override fun onDestroy() {
super.onDestroy()
job.cancel()
}
}
编辑:将 Dispatchers.Main
更改为 Dispatchers.IO
SupervisorJob()
(Kotlin GitHub) 是一个提供单向取消的作业;它允许取消传播 仅向下 .
The SupervisorJob ... is similar to a regular Job with the only exception that cancellation is propagated only downwards. [KotlinLang.org]
用例:您有一项服务可以创建日志条目、检查设置,并根据这些设置继续执行某些操作。例如,如果基于设置值的作业 运行 抛出异常,您是否希望取消父作业(范围)的所有子作业?如果不是(即你仍然希望你的日志记录和检查设置作业至少完成)那么你想使用 SupervisorJob()
,甚至 supervisorScope
(Kotlin GitHub) for 'scoped concurrency' [KotlinLang.org],因为两者都提供单向作业取消 - 并且在在这种情况下,提供的答案有效。
Coroutine Exception Handling - Supervision (KotlinLang.org)
但是,有一个更直接的解决方案可以回答这个问题。
要为您的服务提供 运行 协程(或暂停函数)执行阻塞代码的范围,您只需创建一个新的 CoroutineScope()
with an EmptyCoroutineContext
:
(来自 CoroutineScope 文档的片段)
If the given context does not contain a Job element, then a default Job()
is created. This way, cancellation or failure of any child coroutine in this scope cancels all the other children, just like inside coroutineScope block [Kotlin GitHub]
class YourClass : Extended() {
...
private val serviceScope: CoroutineScope( EmptyCoroutineContext )
...
private inner class ServiceHandler( looper: Looper ): Handler( looper ) {
override fun handleMessage( msg: Message ) {
super.handleMessage( msg )
serviceScope.launch {
try{
+ ...
} catch( e: Exception ) {
+ ...
} finally {
stopSelf( msg.arg1 )
}
}
}
}
override fun onCreate(){
+ ...
}
override fun onDestroy(){
/* In a service, unlike in an activity, we do not
need to make a call to the super implementation */
//super.onDestory()
serviceScope.cancel()
}
}
我就是这样工作的
import androidx.lifecycle.lifecycleScope
class ServiceLife : LifecycleService() {
private var supervisorJob = SupervisorJob(parent = null)
override fun onCreate() {
super.onCreate()
val serviceJob = lifecycleScope.launch {
//some suspend fun
}
supervisorJob[serviceJob.key]
supervisorJob.cancel()
}
}
如何提供作用域或如何从服务中调用挂起函数Android? 通常,activity 或 viewmodel 为我们提供了范围,我们可以从那里启动暂停,但 Service
中没有类似的东西您可以创建自己的 CoroutineScope
with a SupervisorJob
,您可以在 onDestroy()
方法中取消。只要您的服务被使用,使用此范围创建的协同程序就会存在。一旦您的服务 onDestroy()
被调用,所有以此范围启动的协程都将被取消。
class YourService : Service() {
private val job = SupervisorJob()
private val scope = CoroutineScope(Dispatchers.IO + job)
...
fun foo() {
scope.launch {
// Call your suspend function
}
}
override fun onDestroy() {
super.onDestroy()
job.cancel()
}
}
编辑:将 Dispatchers.Main
更改为 Dispatchers.IO
SupervisorJob()
(Kotlin GitHub) 是一个提供单向取消的作业;它允许取消传播 仅向下 .
The SupervisorJob ... is similar to a regular Job with the only exception that cancellation is propagated only downwards. [KotlinLang.org]
用例:您有一项服务可以创建日志条目、检查设置,并根据这些设置继续执行某些操作。例如,如果基于设置值的作业 运行 抛出异常,您是否希望取消父作业(范围)的所有子作业?如果不是(即你仍然希望你的日志记录和检查设置作业至少完成)那么你想使用 SupervisorJob()
,甚至 supervisorScope
(Kotlin GitHub) for 'scoped concurrency' [KotlinLang.org],因为两者都提供单向作业取消 - 并且在在这种情况下,提供的答案有效。
Coroutine Exception Handling - Supervision (KotlinLang.org)
但是,有一个更直接的解决方案可以回答这个问题。
要为您的服务提供 运行 协程(或暂停函数)执行阻塞代码的范围,您只需创建一个新的 CoroutineScope()
with an EmptyCoroutineContext
:
(来自 CoroutineScope 文档的片段)
If the given context does not contain a Job element, then a default
Job()
is created. This way, cancellation or failure of any child coroutine in this scope cancels all the other children, just like inside coroutineScope block [Kotlin GitHub]
class YourClass : Extended() {
...
private val serviceScope: CoroutineScope( EmptyCoroutineContext )
...
private inner class ServiceHandler( looper: Looper ): Handler( looper ) {
override fun handleMessage( msg: Message ) {
super.handleMessage( msg )
serviceScope.launch {
try{
+ ...
} catch( e: Exception ) {
+ ...
} finally {
stopSelf( msg.arg1 )
}
}
}
}
override fun onCreate(){
+ ...
}
override fun onDestroy(){
/* In a service, unlike in an activity, we do not
need to make a call to the super implementation */
//super.onDestory()
serviceScope.cancel()
}
}
我就是这样工作的
import androidx.lifecycle.lifecycleScope
class ServiceLife : LifecycleService() {
private var supervisorJob = SupervisorJob(parent = null)
override fun onCreate() {
super.onCreate()
val serviceJob = lifecycleScope.launch {
//some suspend fun
}
supervisorJob[serviceJob.key]
supervisorJob.cancel()
}
}