产品需求:
主播或其它用户,当收到用户送的礼物消息(动态消息和静态消息)后要判断此消息与上一次收到的消息时间间隔小于2秒,并且是相同的用户送相同的礼物时,主播和用户界面上 【礼物提示】要显示连击特效, 如否,则不显示连击特效, 消息显示完后,正常退出即可。效果如下图
产品要求:要实现2秒内相同用户送相同的礼物,要根据消息的id进行排序并且实现续连。其它情况按礼物正常排序,先来的礼物优先显示。
专业述语:
礼物提示特效:
指 从屏幕左边向右跳出的带 提示方案(xxx 送了小心心)的飘窗
礼物动画特效:
指 界面上播放的svga 动画 (如上图中从下往上飞的 火箭)。
动态礼物特效:
指 在礼物提示特效的基础上还要有 礼物动画特效 。即:(礼物提示特效 + 礼物动画特效)
静态礼物消息:
指 只有礼物提示特效的消息
动态礼物消息 :
指具有 动态礼物特效的消息
连击特效:
指 相同的用户送相同的礼物,并且用户收到的两次消息间隔时间小于2秒时,礼物提示数量文案带叠加的特效。它是 一个特殊的 礼物提示特效。
UI显示位置
界面上要有A(上图中带酒字图标的区域)和B两个区域(上图中带火箭图标的区域):
1,A区域专门用于显示 静态礼物消息 ,需要同步处理,同步规则如下:
2,B区域专门用于显示 动态礼物消息,需要同步处理,同步规则如下:
同步的具体规则 如下(前置条件):
1 动态礼物消息的同步 :
指:礼物提示特效和礼物动画特效 ,要同时开始播放,,但不要求两者同时从界面上消失,,两者有一方播放完,即可离开界面,在后台等待另一方播放完后,再去请求播放下条消息
(两者开始播放的时间点要同步, 只有当二者都播放完后,下条消息才可以播放。 这条语句有歧义,不如上条明确)
1 静态礼物消息的同步 :
指: 连击的静态礼物消息或单个的静态礼物消息,正常播放完动画后,再依次播放下一个消息。
动画播放过程:
礼物消息如何收发:
发送礼物:
用户调用后端送礼物接口后,由后端往该IM 聊天群中发送自定义消息(注:一场直播会产生一个音视频聊天室)
接收礼物:
用户收到自定义消息后自行解析,判断是否是该群消息,及后续的入队处理。
礼物消息的数据格式:
"type": 3,
"msg": {
"userId": "userId",
"userName": "用户名",
"nickName": "用户昵称",
"userIcon": "用户头像url",
"giftNum": "该用户的第几个礼物",
"giftIcon": "礼物icon的url",
"giftName": "礼物的名称"
"id": "礼物的id"
}
礼物消息特点:
1,一般情况下先进先出
2,有序,两消息,间隔2s内, 同一个用户送相同的礼物要有连击效果,并且礼物消息要按消息id,进行排序。比如:
(用户连续送了3个相同礼物,礼物属性 giftNum【该用户的第几个礼物】分别为:x1,x2,x3),但由于网络延时用户收到的消息顺序可能为x1,x3,x2,或 x3,x2,x1,如果不排序 会出现 用户界面上会出现 先显示 【用户xxx 送了1个礼物】,然后在出现【用户xxx 送了3个礼物】,最后出现【用户xxx 送了2个礼物】 ,这种异常情况。
3,消息的过滤
如果用户收到了消息x1,x3,但由于网络原因, x2消息在 用户界面刚播放完 x3 后,才入队列,这种异常情况,我们是不需要在播放消息x2的,不然,容易误导主播 (认为用户又送出了2个)。
我们需要用当前播放完的消息(id)过滤掉, 之前的x2 消息提醒(但礼物动画还得加入动画队列中),送礼物的消息在送出时会生产自增的消息id。
消息入队要处理的情况:
1,用户送礼物两消息间隔时间2秒内依次送不同的礼物
如送礼物A,礼物B,礼物C。 由于用户发送的次序依次为A,B,C,但用户收到礼物的礼物顺序可能为C,B,A等。 所以入队的顺序以客户端收到IM 消息的顺序为准 。
2 ,用户送礼物两消息间隔时间2秒内依次送相同的礼物 ,
3 ,用户2秒内既送相同的礼物又送不同的礼物 (A,B为不同礼物,角标数字为第几次送该礼物)
A1---> 1s后B1 ---> 1s后A2 --->1.5s后B2
暂不考虑网络延时情况,当礼物A1入队后播放(还未完全播放完),B1入队后,又来了A2,这时队列中的礼物顺序如下所示,因为需求要求,2秒内如果用户送了相同的礼物要有连击效果。
A1---> A2 ---> B1
4,每隔2秒既送相同的礼物又送不同的礼物
A1---> 2s后B1 ---> 2s后A2 --->2s后B2
这种情况,由于A1和A2时间差已经越过2秒,,服务器端会做处理不当作连击处理。 这两条消息的礼物提示都为:
用户XXX 送了1个小心心等。
不会是如下的情况
用户XXX 送了1个小心心等,
用户XXX 送了2个小心心等,
判断礼物是否连击的条件:
当前播放的消息和即将要播放的消息需满足如下条件:
两消息间隔 不越过2s
两消息是相同用户送的,
送的是同一个礼物,
消息要按id排序
消息入队的具体处理流程:
此处后续更新
消息容器选型及数据结构如何定义:
用什么样的数据结构能很好的处理这个事情呢。
由于礼物消息经常会新增,插入和删除,集合长度不固定扩容代价小(不需要移动元素),,所以我们选型为链表,虽然查询没数组快,但其它优点突出。
LinkedBlockingQueue 可指定固定容量大小 ,,可阻塞(只是我们代码中使用前加判断了,没使用),
由于连击消息要有序,所以我们需要定义另一个集合来对连击的消息进行排序。我们选用 PriorityBlockingQueue,
PriorityBlockingQueue是一个支持优先级的无界队列。默认情况下元素采取自然顺序排列,也可以通过比较器comparator来指定元素的排序规则。 数据结构类图如下:
最终效果
SVGA框架:
SVGAPlayer-Android
使用时偶到的问题:
1 ,切换环境时,要清除SVGA的缓存目录,不然会出现,送礼物后界面上不显示SVGA动画的情况(通过打log,程序是正常的,各回调方法正常执行)
2,ios和android 播放相同的svga时(比如火箭)SVGA背影有差异,但后台提测后使用UI 提供的SVGA 时无此问题
开发过程中出过问题的地方:
判断giftEffectUrl是否为空,为空是静态消息,否则为动态消息,
判断队列是否为空,为空增加元素后,还需要判断当前队列中的动画是否执行完成了,执行完成后才可以取元素开启动画,否则只能添加元素,,(如果队列为空,但队列中的动画没执行完,这时取消息,动画会中止)。 礼物动效队列处理方式和此处一致