前言
在我的Android实现简易轻量下载器:单线程任务队列文章中,有提到过任务队列。当时是需要下载,实现一个简单的单线程任务队列即可。
最近项目中也需要用到任务队列,并且有2种需求:
- 动态礼物动画:在用户送完动态礼物之后,会在界面上展现一个动画。界面上一次最多能执行1个动画,动画按顺序执行。即:
一个入口一个出口
。 - 静态礼物动画:在用户送完静态礼物之后,会在界面上展现一个动画。界面上一次最多能并列执行2个动画,动画按顺序执行。即:
一个入口两个出口
。
同样都是任务队列,只不过一个是只有一个出口,另一个有两个出口。
动态礼物动画
参照着之前那篇文章,很快就写出来了。
动态礼物单体类DynamicGiftModel
:
1 | public class DynamicGiftModel implements GiftModel { |
动态礼物队列类DynamicGift
:
1 | public class DynamicGift { |
说明一下:GifImageView
就是用来播放gif的ImageView,GifDrawable
就是gif对应的drawable,DynamicGiftListener
就是动画执行前后的回调。
可以看到,我们通过execute()
将一个DynamicGiftModel
任务放入到队列中,DynamicGiftModel
调用startAnimation()
便能开始动画了。DynamicGiftExecutor
与那篇博客中的类似。只不过我这里做了一些修改:下载中使用的Runnable,他是同步的,在执行完之后会自动去取一下。但是在这里,动画执行是异步的,我在调用完startAnimation()
之后就会立即返回,所以需要一个监听(GiftAnimationEndListener)在动画执行完毕之后才去执行scheduleNext()
操作,即取下一个任务。
GiftAnimationEndListener代码很简单:
1 | public interface GiftAnimationEndListener { |
调用如下代码将任务添加到队列便能顺序播放动画了。
1 | DynamicGift.getInstance().addGifAnimation(gifImageView, gifDrawable, listener); |
静态礼物动画
静态礼物因为有两个出口,之前没思考过,所以花了一些时间。
静态礼物单体类DynamicGiftModel
:
1 | public class StaticGiftModel implements GiftModel { |
静态礼物队列类StaticGift
:
1 | public class StaticGift { |
可以看到,我在StaticGiftExecutor
中定义了2个变量mActive1
、mActive2
,他们即代表两个出口。在execute
中先判断mActive1
是否为空,是则取出元素给它,让它执行动画。否则判断mActive2
是否为空,是则取出元素给它,让它执行动画。
因为有两个出口,队列并不知道我的下一个任务要在哪个出口执行,所以具体的播放逻辑不能写在其中,所以我将具体的播放逻辑设计在StaticGiftListener.startStaticAnimation()
的中,由调用的用户自行实现,并且在动画结束时,我需要回调队列的接口,来通知队列某某出口的动画执行完毕了。
实现片段代码如下:
1 | /** |
静态礼物动画实现类StaticGiftView:
1 | public class StaticGiftView extends TextView { |
静态礼物是通过StaticGiftView
的setNum()
方法来显示动画的,就是显示一个数量递增,同时伴随着缩放的动画。
页面布局中有staticLayout1
和staticLayout2
,分别代表两个执行动画的布局,通过判断getVisibility()
是否为GONE
来决定是否将动画分发给这个布局。在动画开始时,将布局设置成VISIBLE,在动画结束后,再将布局设置成GONE。
我通过setOver(true)
来告知队列某某出口的动画执行完毕,然后队列回调到onGiftAnimationEnd()
中,继续取出任务分配给有空的出口。
调用如下代码将任务添加到队列便能顺序播放动画了。
1 | StaticGift.getInstance().addNumAnimation(pushGift, listener); |
待优化
- 代码之间的依赖很重,任务队列直接依赖到了前端的UI组件,需要解耦。
- 若是增加至三个、四个或是更多个出口,代码就得一直添加
mActive
了,不利于拓展。