阅读 617

Dialog 按照顺序弹窗

背景: 产品需求,在同一个页面弹窗需要按照顺序

实现: 利用PriorityQueue现实,支持相同优先级,按插入时间排序,目前仅支持Activity,不支持Fragment

代码: DialogPriorityUtil 实现优先级弹窗

/**
 * ClassName: DialogPriorityUtil
 * Description: show dialog by priority
 * author Neo
 * since 2021-09-15  20:15
 * version 1.0
 */
object DialogPriorityUtil : LifecycleObserver {

    private val dialogPriorityQueue = PriorityQueue<PriorityDialogWrapper>()

    private var hasDialogShowing = false

    @MainThread
    fun bindLifeCycle(appCompatActivity: AppCompatActivity) {
        appCompatActivity.lifecycle.addObserver(this)
    }

    @MainThread
    fun showDialogByPriority(dialogWrapper: PriorityDialogWrapper? = null) {
        if (dialogWrapper != null) {
            dialogPriorityQueue.offer(dialogWrapper)
        }
        if (hasDialogShowing) return
        val maxPriority: PriorityDialogWrapper = dialogPriorityQueue.poll() ?: return
        if (!maxPriority.isShowing()) {
            hasDialogShowing = true
            maxPriority.showDialog()
        }
        maxPriority.setDismissListener {
            hasDialogShowing = false
            showDialogByPriority()
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun onDestroy() {
        dialogPriorityQueue.clear()
    }
}
复制代码
/**
 * 定义dialog优先级
 * @property priority Int
 * @constructor
 */
sealed class DialogPriority(open val priority: Int) {
    sealed class HomeMapFragment(override val priority: Int) : DialogPriority(priority) {
        /**
         * App更新
         */
        object UpdateDialog : HomeMapFragment(0)

        /**
         * 等级提升
         */
        object LevelUpDialog : HomeMapFragment(1)

        /**
         * 金币打卡
         */
        object CoinClockInDialog : HomeMapFragment(2)
    }
}

/**
 * ClassName: PriorityDialogWrapper
 * Description: 优先级弹窗包装类
 * author Neo
 * since 2021-09-15  20:20
 * version 1.0
 */
class PriorityDialogWrapper(private val dialog: Dialog, private val dialogPriority: DialogPriority) : Comparable<PriorityDialogWrapper> {

    private var dismissCallback: (() -> Unit)? = null

    private val timestamp = SystemClock.elapsedRealtimeNanos()

    init {
        dialog.setOnDismissListener {
            dismissCallback?.invoke()
        }
    }

    fun isShowing(): Boolean = dialog.isShowing

    fun setDismissListener(callback: () -> Unit) {
        this.dismissCallback = callback
    }

    fun showDialog() {
        dialog.show()
    }

    override fun compareTo(other: PriorityDialogWrapper): Int {
        return when {
            dialogPriority.priority > other.dialogPriority.priority -> {
                // 当前对象比目标对象大,则返回 1
                1
            }
            dialogPriority.priority < other.dialogPriority.priority -> {
                // 当前对象比目标对象小,则返回 -1
                -1
            }
            else -> {
                // 若是两个对象相等,则返回 0
                when {
                    timestamp > other.timestamp -> {
                        1
                    }
                    timestamp < other.timestamp -> {
                        -1
                    }
                    else -> {
                        0
                    }
                }
            }
        }
    }
}
复制代码

使用:

AppCompatActivity

DialogPriorityUtil.bindLifeCycle(this)
DialogPriorityUtil.showDialogByPriority(...)
复制代码
文章分类
Android
文章标签