一、背景
由于业务需要,页面中通常会有很多弹窗功能。并且由于叠加展示的用户体验不好的原因,这些弹窗通常会被要求互斥出现。
在之前的设计里,这些弹窗是杂乱没有管理的。每次新添加一个弹窗业务,需要考虑与已有弹窗的互斥出现。这种无管理弹窗的实现方式主要有以下缺点:
1、需要对各弹窗出现逻辑进行状态区分,以达到互斥。每添加一个新弹窗,就需要添加对应的状态进行管理判断。弹窗业务杂糅,且容易遗漏互斥关系。
2、进入页面根据每个弹窗业务的展示逻辑来判断是否触发该弹窗的展示,因此无论触发的弹窗业务是否成功,其余弹窗都没有机会展示。弹窗少了当次可能的曝光机会。
3、目前没支持弹窗的顺序展现,如果要支持,各弹窗逻辑会互相耦合。
针对上述痛点,需要对业务弹窗进行抽象和统一管理,以达到按权重自行进行排序弹出的目的。最终实现以下功能:
1、各弹窗逻辑隔离,是否弹出完全由弹窗管理类决定。高优先级弹窗失败,会按照优先级高低弹出低优先级弹窗。
2、弹窗出现的优先级由接口动态下发,可以根据产品需要,动态调整弹窗出现优先级。
二、实现
1、弹窗抽象
1)弹窗类型定义:PopType
使用枚举实现,用于区分不同的弹窗。
2)弹窗实体对象:PopData
针对弹窗数据的抽象,弹窗的数据实体,定义了弹窗类型、唯一标识id、弹窗内容。
3)弹窗任务:Task
弹窗业务逻辑的具体执行体,包括但不限于网络请求等任务,用于产生弹窗数据和优先级排序。定义了任务唯一标识id、优先级,并且实现了Comparable接口用于排序。
2、弹窗任务管理类TaskManager
用于管理弹窗出现,主要维护一个弹窗任务优先级队列,按优先级顺序决定哪个弹窗可以弹出。
首先弹窗Task实现了Comparable接口 使其具备通过优先级比较大小的能力
TaskManager内部使用PriorityQueue作为弹窗任务容器,PriorityQueue内部使用**堆排序对内部元素进行排序,**每添加或删除一个Task元素都会对队列按优先级进行调整。
每次任务返回数据时,如果该任务是顶部Task,则直接弹出该任务对应的弹窗。否则,将弹窗数据入队列。
如果弹窗Task未返回正常数据,则将任务队列中该Task移除。并判断当前TaskQueue中的顶部Task是否有返回值,有则弹出;否则,继续等待下个任务的返回结果,重复上述过程。
架构设计如下图所示: