Android Kotlin实现串行任务队列及任务间延迟执行方案咨询
Android Kotlin 串行任务队列最优实现方案
在Android Kotlin环境下,基于Kotlin协程+Channel是实现这类串行任务队列的最优方案——它天然支持动态添加任务、串行执行逻辑,且能简洁处理任务间的延迟需求,同时适配Android的异步操作场景(如文件下载、网络请求)。
核心实现思路
- 用
Channel作为任务队列载体,支持无限动态添加任务; - 启动后台协程循环从
Channel取任务,保证串行执行; - 任务完成后通过协程
delay()函数实现指定延迟,再启动下一个任务; - 任务采用
suspend函数类型,天然适配异步操作,避免回调地狱。
完整代码实现
串行任务队列类
import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel class SerialTaskQueue( private val postTaskDelayMs: Long = 0, // 任务完成后到下一个任务启动的延迟时间 private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default) ) { // 无界Channel,支持无限添加任务 private val taskChannel = Channel<suspend () -> Unit>(Channel.UNLIMITED) init { // 启动协程循环处理任务 scope.launch { for (task in taskChannel) { runCatching { task() // 执行当前任务 }.onFailure { // 任务执行异常处理,可替换为日志上报等逻辑 it.printStackTrace() }.finally { // 任务完成后延迟(如果设置了延迟时间) if (postTaskDelayMs > 0) { delay(postTaskDelayMs) } } } } } // 添加任务到队列 fun addTask(task: suspend () -> Unit) { taskChannel.trySend(task) } // 关闭队列,不再接收新任务,已加入的任务会执行完成 fun shutdown() { taskChannel.close() } }
使用示例(文件下载场景)
// 初始化队列:每个任务完成后延迟1秒再启动下一个,绑定页面生命周期避免内存泄漏 val downloadQueue = SerialTaskQueue(postTaskDelayMs = 1000, scope = lifecycleScope) // 用户触发第一个下载任务 downloadQueue.addTask { downloadFile("https://example.com/file1.apk") println("第一个文件下载完成") } // 用户后续点击添加第二个下载任务 downloadQueue.addTask { downloadFile("https://example.com/file2.apk") println("第二个文件下载完成") } // 模拟suspend类型的下载函数(实际项目中可替换为Retrofit/OkHttp的异步请求) private suspend fun downloadFile(url: String) { // 模拟下载耗时3秒 delay(3000) }
方案优势
- 适配Android异步场景:任务采用
suspend函数,可直接处理网络请求、文件IO等异步操作,无需嵌套回调; - 轻量高效:协程是轻量级线程,相比传统线程池,不会占用过多系统资源;
- 灵活可控:支持动态添加任务、设置任务间延迟,还可通过
CoroutineScope(如lifecycleScope、viewModelScope)自动绑定生命周期,避免内存泄漏; - 异常安全:通过
runCatching捕获任务异常,单个任务失败不会导致整个队列终止; - 易于扩展:可快速添加任务优先级、暂停/恢复队列等扩展功能。
替代方案的不足
- Handler+Runnable:仅适合简单同步任务,处理异步操作需嵌套回调,代码冗余;
- 单线程ThreadPoolExecutor:线程资源占用更高,任务间延迟需手动实现(如
Thread.sleep()),且无法直接适配协程异步逻辑。
内容的提问来源于stack exchange,提问作者M. Usman Khan
相关产品推荐
相关产品推荐

