Android中多個彈窗的排隊展示
在實際的開發(fā)中哥力,我們會遇到多個彈窗的問題喊衫,又不能一次全部彈出治拿,所以我們的代碼就是 if else if else 循環(huán)嵌套逃糟。
例如我們在工作詳情中申請一個工作析既,首先我們就要走一個校驗接口躬贡,然后接口會告訴需要判斷的對象。如下判斷邏輯:
- 首先需要先判斷是否是新用戶眼坏,如果是新用戶需要去參加線上培訓(xùn)(跳轉(zhuǎn)頁面)
- 判斷用戶是否完善了個人信息拂玻,如果沒有需要去完善個人信息 (跳轉(zhuǎn)頁面)
- 判斷個人用工狀態(tài)是否是Approve,如果個人狀態(tài)不對需要聯(lián)系管理員 (撥打電話)
- 判斷當(dāng)前用戶是否填寫了每日新冠報告宰译,如果沒有需要填寫新冠表單(跳轉(zhuǎn)瀏覽器)
- 判斷當(dāng)前申請的工作是否需要押金檐蚜,如果要押金彈框提示(彈框)
- 如果需要押金,你的錢包又恰好有錢沿侈,會提示是否把錢包的錢充值到押金(彈框)
- 如果改工作需要人臉信息闯第,需要你采集人臉 (跳轉(zhuǎn)頁面)
- 如果是非直營的工作,會提示你非自營工作 (彈窗)
- 如果該工作需要what's app 會彈窗提示你輸入賬號 (彈框)
- 如果該工作是銀行卡結(jié)算缀拭,你又沒有銀行卡信息咳短,需要填寫銀行卡(新頁面)
...
真實業(yè)務(wù)肯定不止10個條件了肃廓,這里就先寫10個吧。來诲泌,鍵盤給你盲赊,你來寫if else 。你寫完了敷扫? 中間第5個后面再加一個判斷 如果你沒有填寫技能 去新頁面填寫你的技能哀蘑! 這么多if else 中你真的改的動嗎?
什么葵第?你業(yè)務(wù)中就是這么寫的绘迁?你改的動?
就喜歡這種樸實無華的程序員卒密,但是呢相信我缀台,真的非常簡單。畢竟偷懶才是程序員的第一生產(chǎn)力哮奇,所有的設(shè)計模式膛腐,框架,封裝什么的鼎俘,都是為了偷懶哲身,讓我們更輕松一點。來吧贸伐,看看我的實現(xiàn)勘天!
一、攔截器模式的定義
真正的實現(xiàn): 定義攔截器接口
interface Interceptor {
fun intercept(chain: InterceptChain)
}
定義一個攔截器的基類
abstract class BaseInterceptImpl : Interceptor {
protected var mChain: InterceptChain? = null
@CallSuper
override fun intercept(chain: InterceptChain) {
mChain = chain
}
}
具體的邏輯都在攔截鏈管理類中
class InterceptChain private constructor(
// 彈窗的時候可能需要Activity/Fragment環(huán)境捉邢。
val activity: FragmentActivity? = null,
val fragment: Fragment? = null,
private var interceptors: MutableList<Interceptor>?
) {
companion object {
@JvmStatic
fun create(count: Int = 0): Builder {
return Builder(count)
}
}
private var index: Int = 0
// 執(zhí)行攔截器脯丝。
fun process() {
interceptors ?: return
when (index) {
in interceptors!!.indices -> {
val interceptor = interceptors!![index]
index++
interceptor.intercept(this)
}
interceptors!!.size -> {
clearAllInterceptors()
}
}
}
private fun clearAllInterceptors() {
interceptors?.clear()
interceptors = null
}
// 構(gòu)建者模式。
open class Builder(private val count: Int = 0) {
private val interceptors by lazy(LazyThreadSafetyMode.NONE) {
ArrayList<Interceptor>(count)
}
private var activity: FragmentActivity? = null
private var fragment: Fragment? = null
// 添加一個攔截器伏伐。
fun addInterceptor(interceptor: Interceptor): Builder {
if (!interceptors.contains(interceptor)) {
interceptors.add(interceptor)
}
return this
}
// 關(guān)聯(lián)Fragment宠进。
fun attach(fragment: Fragment): Builder {
this.fragment = fragment
return this
}
// 關(guān)聯(lián)Activity。
fun attach(activity: FragmentActivity): Builder {
this.activity = activity
return this
}
fun build(): InterceptChain {
return InterceptChain(activity, fragment, interceptors)
}
}
}
二秘案、攔截器模式的使用
三個簡單的文件就定義了一個攔截器鏈砰苍,我們看看上面的需求我們?nèi)绾螌崿F(xiàn)
具體到工作申請判斷類
public class JobInterceptBean {
public boolean isNewMember;
public boolean isFillInfo;
public boolean isMemberApprove;
public boolean isNOCVUpload;
public boolean isNeedDepost;
public boolean isNeedFace;
public boolean isUnderCompany;
public boolean isNeedWhatApp;
public boolean isNeedBankInfo;
public boolean isNeedSkill;
...
}
具體的攔截器一潦匈,新用戶的攔截阱高。這里直接暴力的跳轉(zhuǎn)頁面
class InterceptNewMember(private val bean: JobInterceptBean) : BaseInterceptImpl() {
override fun intercept(chain: InterceptChain) {
super.intercept(chain)
if (bean.isNewMember) {
//攔截
//可以不彈窗,直接就暴力跳轉(zhuǎn)新頁面
Demo5Activity.startInstance()
} else {
//放行- 轉(zhuǎn)交給下一個攔截器
chain.process()
}
}
//已經(jīng)完成了培訓(xùn)-放行
fun resetNewMember() {
mChain?.process()
}
}
完善信息的攔截茬缩,這里使用彈窗判斷
class InterceptFillInfo(private val bean: JobInterceptBean) : BaseInterceptImpl() {
override fun intercept(chain: InterceptChain) {
super.intercept(chain)
if (!bean.isFillInfo) {
//攔截
//跳轉(zhuǎn)新頁面
showDialogTips(chain)
} else {
//放行- 轉(zhuǎn)交給下一個攔截器
chain.process()
}
}
private fun showDialogTips(chain: InterceptChain) {
FangIOSDialog(chain.activity).apply {
setTitle("完善信息")
setMessage("你沒有完善信息赤惊,你要去完善信息")
setNegativeButton("跳過"){
dismiss()
chain.process()
}
setPositiveButton("去完善"){
Demo5Activity.startInstance()
}
show()
}
}
}
用戶狀態(tài)使用彈窗判斷
class InterceptMemberApprove(private val bean: JobInterceptBean) : BaseInterceptImpl() {
override fun intercept(chain: InterceptChain) {
super.intercept(chain)
if (!bean.isMemberApprove) {
//攔截
showDialogTips(chain)
} else {
//放行- 轉(zhuǎn)交給下一個攔截器
chain.process()
}
}
private fun showDialogTips(chain: InterceptChain) {
FangIOSDialog(chain.activity).apply {
setTitle("狀態(tài)不對")
setMessage("你用戶狀態(tài)不對,聯(lián)系管理員嗎凰锡?")
setNegativeButton("跳過") {
dismiss()
chain.process()
}
setPositiveButton("聯(lián)系") {
dismiss()
toast("去撥打電話未舟,當(dāng)你狀態(tài)對了才能繼續(xù)")
}
show()
}
}
}
技能的攔截-使用彈窗判斷
class InterceptSkill(private val bean: JobInterceptBean) : BaseInterceptImpl() {
override fun intercept(chain: InterceptChain) {
super.intercept(chain)
if (bean.isNeedSkill) {
//攔截
//跳轉(zhuǎn)新頁面
showDialogTips(chain)
} else {
//放行- 轉(zhuǎn)交給下一個攔截器
chain.process()
}
}
private fun showDialogTips(chain: InterceptChain) {
FangIOSDialog(chain.activity).apply {
setTitle("你沒有填寫技能")
setMessage("你要去填寫技能嗎圈暗?")
setNegativeButton("跳過") {
dismiss()
chain.process()
}
setPositiveButton("去填寫") {
Demo5Activity.startInstance()
}
show()
}
}
}
內(nèi)部可以使用 Dialog 或者 PopupWindow 或者第三方的彈窗庫,都是可以的裕膀。具體的可以自行實現(xiàn)员串。下面看看如何使用
lateinit var newMemberIntercept: InterceptNewMember
fun navIntercept() {
//模擬網(wǎng)絡(luò)請求
LoadingDialogManager.get().showLoading(this@Demo4Activity)
CommUtils.getHandler().postDelayed({
LoadingDialogManager.get().dismissLoading()
val bean = JobInterceptBean(true, false, false, false, true, true, true, true, true, true)
createIntercept(bean)
}, 1500)
}
//創(chuàng)建攔截彈窗
private fun createIntercept(bean: JobInterceptBean) {
newMemberIntercept = InterceptNewMember(bean)
val chain = InterceptChain.create(4)
.attach(this@Demo4Activity)
.addInterceptor(newMemberIntercept)
.addInterceptor(InterceptFillInfo(bean))
.addInterceptor(InterceptMemberApprove(bean))
.addInterceptor(InterceptSkill(bean))
.build()
//開始執(zhí)行
chain.process()
}
我們把 NewMemberIntercept 單獨提取出來作為成員變量是為了接受到完成培訓(xùn)的通知,對它做放行操作昼扛。
override fun startObserve() {
LiveEventBus.get("newMember",Boolean::class.java).observe(this){
//調(diào)用內(nèi)部放行的方法
newMemberIntercept.resetNewMember()
}
}
看看效果寸齐,NewMemberIntercept 放行與不放行的區(qū)別
可以看到我們的第二個攔截器 InterceptFillInfo 它內(nèi)部就沒有定義放行的方法,如果一旦跳轉(zhuǎn)到新頁面抄谐,但是沒有接收通知去放行的話就會卡在這里渺鹦。
效果:
總結(jié)
這樣就完成了一個攔截器鏈,我們可以自由的定義彈窗蛹含,打電話毅厚,跳轉(zhuǎn)頁面,跳轉(zhuǎn)瀏覽器等自定義的功能浦箱。
我們的業(yè)務(wù)場景是調(diào)用接口獲取到全部的校驗數(shù)據(jù)吸耿,然后再創(chuàng)建 Chain 。當(dāng)然我們也可以先創(chuàng)建 Chain 酷窥。然后把每一個攔截器都設(shè)置為成員變量珍语,每一個攔截器可以調(diào)用不同的接口做校驗,當(dāng)數(shù)據(jù)返回的時候設(shè)置給攔截器暴露的方法竖幔,內(nèi)部再判斷數(shù)據(jù)類型板乙,是否需要放行。
可以說這是一種非常靈活的攔截器鏈拳氢,內(nèi)部使用了責(zé)任鏈模式募逞,單例模式,建造者模式馋评,工廠模式等放接。如果大家有需要可以使用起來长赞。
具體的源碼在此牲证。如有錯漏還請指出,如果有更好的方法也歡迎討論栓霜。
如果覺得不錯還請點贊
支持哦蜕青!
到此完結(jié)苟蹈!