前言
在我的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了,不利于拓展。