英文:
How to make Kotlin's LifecycleScope has sequential behaviour as Java's Executors.newSingleThreadExecutor?
问题
In Java Android, 为了在不阻塞主线程的情况下实现顺序行为,我正在使用以下代码。
Java Android
private static final ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> task0());
executor.execute(() -> task1());
executor.execute(() -> task2());
上述代码将始终按照task0
,task1
和task2
函数的确切顺序执行,不管函数内部发生了什么。
我对Kotlin的LifecycleScope提供的生命周期感知功能印象深刻。我尝试以以下Kotlin的LifecycleScope形式编写代码。
Kotlin Android
val dispatcherForCalendar = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
lifecycleScope.launch(dispatcherForCalendar) {
task0()
}
lifecycleScope.launch(dispatcherForCalendar) {
task1()
}
lifecycleScope.launch(dispatcherForCalendar) {
task2()
}
上述代码将按照task0
,task1
和task2
函数的确切顺序执行,除非在函数中执行了延迟操作。
- 实际上,我不会在任务函数中显式插入
delay
代码。在这种情况下,Android系统是否仍然可以隐式执行delay
操作? - 如何实现与我的Java代码
Executors.newSingleThreadExecutor
相同的顺序行为?
谢谢。
英文:
In Java Android, to achieve sequential behavior without blocking main thread, this is the code I am using.
Java Android
private static final ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> task0());
executor.execute(() -> task1());
executor.execute(() -> task2());
The above code, will always execute in the exact order of task0
, task1
and task2
functions regardless what is happening inside the functions.
I am impressed by the life cycle aware feature, offered by Kotlin's LifecycleScope. I try to write the code in the following Kotlin's LifecycleScope form.
Kotlin Android
val dispatcherForCalendar = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
lifecycleScope.launch(dispatcherForCalendar) {
task0()
}
lifecycleScope.launch(dispatcherForCalendar) {
task1()
}
lifecycleScope.launch(dispatcherForCalendar) {
task2()
}
The above code will executed in the exact order of task0
, task1
and task2
functions, except when delay is performed in the functions.
- In reality, I will not insert
delay
code explicitly in task functions. In such a case, can Android system still performdelay
operation implicitly? - How I can achieve sequential behavior, same as my Java code
Executors.newSingleThreadExecutor
?
Thank you.
答案1
得分: 1
Regarding 1):
协程可以在任何suspend
函数调用时将线程返回给调度程序,而不仅仅是在delay()
调用时。
Regarding 2):
我的答案在这里展示了如何使用通道(Channel)构建一个顺序任务队列。您可以在构造函数中注入一个CoroutineScope
,以便在Activity或Fragment中使用时可以传递lifecycleScope
。类似这样:
class JobQueue(
private val scope: CoroutineScope,
private val defaultContext: CoroutineContext = Dispatchers.Main
) {
private val queue = Channel<Job>(Channel.UNLIMITED)
init {
scope.launch(Dispatchers.Default) {
for (job in queue) job.join()
}
}
fun submit(
context: CoroutineContext = defaultContext,
block: suspend CoroutineScope.() -> Unit
) {
synchronized {
val job = scope.launch(context, CoroutineStart.LAZY, block)
queue.trySend(job)
}
}
}
如果这些是阻塞的任务,您可以例如将Dispatchers.IO
作为运行任务的defaultContext
。
英文:
Regarding 1):
The coroutines may yield the thread back to the dispatcher at any suspend
function call, not just at delay()
calls.
Regarding 2):
My answer here shows how you can build a sequential task queue using a Channel. You could modify the class to allow a CoroutineScope
to be injected in the constructor, so lifecycleScope
could be passed in when using it in an Activity or Fragment. Something like this:
class JobQueue(
private val scope: CoroutineScope,
private val defaultContext: CoroutineContext = Dispatchers.Main
) {
private val queue = Channel<Job>(Channel.UNLIMITED)
init {
scope.launch(Dispatchers.Default) {
for (job in queue) job.join()
}
}
fun submit(
context: CoroutineContext = defaultContext,
block: suspend CoroutineScope.() -> Unit
) {
synchronized {
val job = scope.launch(context, CoroutineStart.LAZY, block)
queue.trySend(job)
}
}
}
If these were blocking jobs, you might for example pass Dispatchers.IO
as the defaultContext
for running the jobs.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论