简介
基于kotlin coroutine
的Channel
,实现的一个非阻塞式的任务队列,按先进先出的规则执行任务。
适用场景
适用于多个任务没有依赖关系,需要排队执行的情况。
比如:多个UI展示任务,需要排队一一展示的情况
- 弹框任务编排,例如,app首页有多个弹框(隐私弹框、权限弹框、更新弹框、运营弹框),需要按一定顺序排队展示,一个接一个展示,并且上一个主动关闭之后才能下一个。
- 直播间打赏礼物展示,打赏礼物动画需要一个一个展示的场景,动画展示的时间固定的。
引用
库在jitpack
上
1 | maven { url 'https://jitpack.io' } |
1 | dependencies { |
特性
- 基于
kotlin coroutine
实现。 - First-In,First-out处理任务
- 支持指定task执行在主线程或是子线程
使用
创建任务队列管理类
1
mQueueManager = TaskQueueManager()
添加任务(有固定执行时间的)
1
2
3mQueueManager.sendTask(Task(3000) {
ToastUtils.showShort("btn click: $curCount ,counts")
})添加执行时间不固定的任务(展示一个弹框)
1
2
3
4
5
6
7
8
9
10mQueueManager.sendTask(Task {
PopTip.show("弹框提示: $curCount", "关闭").noAutoDismiss()
.setButton { popTip, v -> //点击“撤回”按钮回调
//延迟1s展示下一个任务
this@MainActivity.mViewBinding.btnShot.postDelayed(1000) {
doNextTask()
}
false
}
})
执行时间不确定的任务,需要在任务执行完后主动调用 doNextTask()
方法去执行下一个task,否则消费者会一直挂起。
注意:还提供了一个全局单例TaskQueueManager.instance
分析
task定义
一类task
是有固定执行时间的,比如展示一个toast
,每次都是展示2s;一类task
是没有固定的执行时间的,比如,app首页各种类型的弹框,权限弹框没有依赖信息,直接展示,如果不关闭的话,会一直展示,表示任务一直在执行中,只有当用户手动关闭弹框时,任务才结束。task
可以执行在主线程,也可以执行在子线程处理耗时任务。执行完当前任务之后会执行下一个任务。
task
支持指定要执行在主线程(默认),还是子线程,如果是执行时间固定的支持指定执行时间,默认是执行时间不固定。
1 | /** |
队列处理
使用channel
构造的生产者,消费者的多对一模型,消费者在消费task
时,生产者被挂起。使用RENDEZVOUS
类型的channel
,没有缓冲区,同一时刻只能执行一个task
,当执行taks
,挂起send
操作。执行task
时切换到指定的Dispatchers.MAIN
或者Dispatchers.IO
协程上下文执行,如果task是执行时间不固定,使用Mutex
挂起channel
的receive
操作所在的coroutine
,当task
执行完毕的恢复channel
的receive
操作所在的coroutine
,同时send
操作所在coroutine
被恢复执行。