Flutter 統(tǒng)一彈窗管理的思考與實(shí)現(xiàn)

背景

??在項(xiàng)目開發(fā)中經(jīng)常會(huì)碰到有時(shí)要根據(jù)業(yè)務(wù)后臺(tái)接口顯示一些提示框或者引導(dǎo)框什么的,有時(shí)這些彈框要多次顯示或只顯示一次,并且它們內(nèi)部也有一定的優(yōu)先級(jí),還要保證一個(gè)一個(gè)的顯示率触,不能重疊。還有一些操作完成后汇竭,進(jìn)入到了指定的頁面才顯示這個(gè)操作之后的提示或引導(dǎo)彈窗葱蝗。特別是在 Flutter 中痊剖,這些還顯示更為復(fù)雜,因?yàn)樵膹棿暗膬?yōu)先級(jí)比 Flutter 的優(yōu)先級(jí)高垒玲,例如權(quán)限申請(qǐng)陆馁、指紋等。

??這就使得處理更為復(fù)雜合愈,通用的處理是在界面通些一些變量來控制當(dāng)前是否有彈窗在顯示叮贩,來判斷其它的彈窗要不要顯示,或者通過標(biāo)識(shí)來確認(rèn)彈窗是否已經(jīng)顯示過佛析;這就使得界面上有各種各樣的臨時(shí)變更益老,及各種判斷,這樣就非常影響整個(gè)界面的可讀性寸莫。

??所以在這里就把項(xiàng)目中一些處理的思路與方法跟大家分享下捺萌,大家一起學(xué)習(xí)。

現(xiàn)狀

  1. 彈窗樣式多樣膘茎、多個(gè)彈窗重疊桃纯、多個(gè)彈窗間有優(yōu)先級(jí)
  2. 有時(shí)彈窗需指定特定頁面
  3. 同一彈窗會(huì)重復(fù)顯示
  4. 彈窗無法指定關(guān)閉

思路

  • 對(duì)于上述場景,對(duì)于自動(dòng)觸發(fā)彈出的彈窗披坏,統(tǒng)一加到彈窗管理中态坦。
  • 對(duì)于沒有指定頁面的彈窗,則加入到頂層頁面中棒拂。彈窗管理有特定頂層頁面伞梯,用于顯示當(dāng)前頂層需顯示的彈窗列表
  • 對(duì)于需要在特定頁面顯示的彈窗,則在需要顯示前判斷當(dāng)前頂層視圖是否為特定頁面(因?yàn)?Flutter 中彈窗無需與頁面關(guān)聯(lián))帚屉。
  • 每個(gè)彈窗都有優(yōu)先級(jí)谜诫,在頁面需要顯示前,會(huì)先進(jìn)行優(yōu)先級(jí)排序攻旦,再根據(jù)排序結(jié)果進(jìn)行展示
  • 每個(gè)彈窗都會(huì)生成一個(gè)固定的唯一標(biāo)識(shí)喻旷,用于處理彈窗重復(fù)問題
  • 對(duì)于彈窗無法指定關(guān)閉的問題,如有需強(qiáng)制顯示的彈窗敬特,則會(huì)先判斷當(dāng)前是否有顯示的彈窗掰邢,有則先 pop彈窗再顯示強(qiáng)制的彈窗

實(shí)現(xiàn)效果

image

解決辦法

DialogManager

image

統(tǒng)一彈窗管理類,管理彈窗的添加及顯示伟阔,詳細(xì)代碼見最后

  • 初始化方法

??初始化方法中生成兩個(gè)數(shù)組List<DialogBean> _dialogList掰伸,_hasShowBeans皱炉。_dialogList用于儲(chǔ)存加入在統(tǒng)一彈窗中的彈窗數(shù)據(jù)
_hasShowBeans用于存儲(chǔ)已經(jīng)顯示過,還沒有清除的彈窗數(shù)據(jù)

??為什么不用單一 bean 去儲(chǔ)存顯示的彈窗數(shù)據(jù)狮鸭,因?yàn)橹脼榭盏奶幚砗辖粒窃趶棿跋У漠惒交卣{(diào)中多搀,如果一個(gè)新的彈窗要顯示,舊的那個(gè)彈窗消失的回調(diào)過來會(huì)把當(dāng)前在顯示的彈窗數(shù)據(jù)置為空灾部,則會(huì)導(dǎo)致當(dāng)前判斷時(shí)否有顯示的彈窗不準(zhǔn)確康铭。

  • add 方法
image

主要用于添加彈窗數(shù)據(jù)在_dialogList中

  1. 假如添加的彈窗為 highClear 或 highClearAll,則會(huì)移除其它低優(yōu)先級(jí)的彈窗赌髓。主要場景是在強(qiáng)制升級(jí)彈窗从藤、多終端登錄彈窗
  2. 對(duì)于重復(fù)添加的彈窗,則不重復(fù)添加
  3. 對(duì)于棧中已經(jīng)存在 highClear 或 highClearAll級(jí)別彈窗锁蠕,則不添加低優(yōu)先級(jí)彈窗
  4. 對(duì)所有的彈窗進(jìn)行優(yōu)先級(jí)排序
  • show 方法

主要用于添加彈窗數(shù)據(jù)在_dialogList中

  1. 假如添加的彈窗為 highClear 或 highClearAll夷野,則會(huì)移除其它低優(yōu)先級(jí)的彈窗。主要場景是在強(qiáng)制升級(jí)彈窗荣倾、多終端登錄彈窗
  2. 對(duì)于重復(fù)添加的彈窗悯搔,則不重復(fù)添加
  3. 對(duì)于棧中已經(jīng)存在 highClear 或 highClearAll級(jí)別彈窗,則不添加低優(yōu)先級(jí)彈窗
  4. 對(duì)所有的彈窗進(jìn)行優(yōu)先級(jí)排序

DialogBean

///dialog唯一標(biāo)識(shí)舌仍,通過 DialogBean 數(shù)據(jù)內(nèi)容生成 Md5生成
String dialogId;

///當(dāng)前 dialog妒貌,顯示的視圖。如果為空铸豁,則在頂層頁面
String pageRouter;

///優(yōu)先級(jí)苏揣、用于顯示彈窗前排序,
///但對(duì)于加入的彈窗推姻,已經(jīng)顯示的情況
///[highClear] 清除已顯示的彈窗平匈,直接顯示當(dāng)前彈窗,該屬性慎用
///[high] 回收當(dāng)前已顯示的彈窗藏古,再顯示高優(yōu)先級(jí)彈窗增炭,該屬性慎用
DialogPriority dialogPriority;

///用于排序
int priority;

///彈窗內(nèi)部業(yè)務(wù) widget,每次show 時(shí)動(dòng)態(tài)創(chuàng)建。不能直接傳創(chuàng)建好的 widget拧晕,因?yàn)樵?high回收時(shí)隙姿,調(diào)用 pop 再 show 會(huì)出現(xiàn) The following NoSuchMethodError was thrown building Builder(dirty):
CreateDialogWidget createDialogWidg

統(tǒng)一的彈窗實(shí)體類,詳細(xì)代碼見最后厂捞。

  1. dialogId,用于彈窗去重
  2. pageRouter用于指定彈窗需顯示的頁面输玷,如果沒有指定,則直接顯示
  3. dialogPriority標(biāo)識(shí)彈窗優(yōu)先級(jí)
  4. priority彈窗優(yōu)先級(jí)擴(kuò)展字段靡馁,主要用于排序
  5. createDialogWidget生成彈窗widget.不用直接使用 widget欲鹏,在 high 回收時(shí),再顯示會(huì)報(bào)異常臭墨。

DialogUtil

image

公共彈窗創(chuàng)建類赔嚎,詳細(xì)代碼見最后

  1. 生成對(duì)應(yīng) dialog 唯一的 id
  2. dialog 業(yè)務(wù)自身內(nèi)部處理
  3. 需要加入統(tǒng)一彈窗管理中 dialog 統(tǒng)一在這里生成

場景驗(yàn)證

多個(gè)彈窗是否按順序依次彈出

DialogManager()
  ..add(
      DialogBean(
        dialogPriority: DialogPriority.high,
        createDialogWidget: () =>
            DialogUtil.createTipWidget(context, "測試彈窗\n 換行
"),
      ))
      ..add(
      DialogBean(
        dialogPriority: DialogPriority.high,
        createDialogWidget: () =>
            DialogUtil.createTipWidget(context, "測試彈窗"),
      ))
  ..show(context);

相同的彈窗是否去重

DialogManager()
  ..add(
      DialogBean(
        dialogPriority: DialogPriority.high,
        createDialogWidget: () =>
            DialogUtil.createTipWidget(context, "測試彈窗"),
      ))
      ..add(
      DialogBean(
        dialogPriority: DialogPriority.high,
        createDialogWidget: () =>
            DialogUtil.createTipWidget(context, "測試彈窗"),
      ))
  ..show(context);

彈窗回收:已彈出低優(yōu)先級(jí)彈窗,顯示高優(yōu)先級(jí)彈窗尤误,是否可以回收顯示

DialogManager()
  ..add(
      DialogBean(
        createDialogWidget: () => DialogUtil.createTipWidget(
          context,
          "測試彈窗\n 換行",
        ),
      ))
  ..show(context);

Future.delayed(Duration(seconds: 1), () {
  DialogManager()
    ..add(
        DialogBean(
          dialogPriority: DialogPriority.high,
          createDialogWidget: () =>
              DialogUtil.createTipWidget(context, "測試彈窗"),
        ))
    ..show(context);
});


可反過來,先顯示高優(yōu)先級(jí)侠畔,再顯示其它

彈窗清除:已彈出低優(yōu)先級(jí)彈窗,顯示高優(yōu)先級(jí)并清除其它的彈窗

DialogManager()
  ..add(
      DialogBean(
        createDialogWidget: () => DialogUtil.createTipWidget(
          context,
          "測試彈窗\n 換行"
        ),
      ))
  ..show(context);

Future.delayed(Duration(seconds: 1), () {
  DialogManager()
    ..add(
        DialogBean(
          dialogPriority: DialogPriority.highClear,
          createDialogWidget: () =>
              DialogUtil.createTipWidget(context, "測試彈窗"),
        ))
    ..show(context);
});

彈窗頁面驗(yàn)證:指定彈窗在指定頁面顯示


Future.delayed(Duration(seconds: 1), () {
  DialogManager()
    ..add(
        DialogBean(
          pageRouter: Router.login,
          createDialogWidget: () => DialogUtil.createTipWidget(
            context,
            "測試彈窗",
          ),
        ))
    ..show(context);
});

最后

??如果在使用過程遇到問題损晤,歡迎下方留言交流软棺。

??代碼下載地址

學(xué)習(xí)資料

請(qǐng)大家不吝點(diǎn)贊!因?yàn)槟狞c(diǎn)贊是對(duì)我最大的鼓勵(lì)尤勋,謝謝喘落!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市斥黑,隨后出現(xiàn)的幾起案子揖盘,更是在濱河造成了極大的恐慌,老刑警劉巖锌奴,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兽狭,死亡現(xiàn)場離奇詭異,居然都是意外死亡鹿蜀,警方通過查閱死者的電腦和手機(jī)箕慧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來茴恰,“玉大人颠焦,你說我怎么就攤上這事⊥妫” “怎么了伐庭?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長分冈。 經(jīng)常有香客問我圾另,道長,這世上最難降的妖魔是什么雕沉? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任集乔,我火速辦了婚禮,結(jié)果婚禮上坡椒,老公的妹妹穿的比我還像新娘扰路。我一直安慰自己,他們只是感情好倔叼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布汗唱。 她就那樣靜靜地躺著,像睡著了一般缀雳。 火紅的嫁衣襯著肌膚如雪渡嚣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天肥印,我揣著相機(jī)與錄音识椰,去河邊找鬼。 笑死深碱,一個(gè)胖子當(dāng)著我的面吹牛腹鹉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播敷硅,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼功咒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了绞蹦?” 一聲冷哼從身側(cè)響起力奋,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎幽七,沒想到半個(gè)月后景殷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡澡屡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年猿挚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驶鹉。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡绩蜻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出室埋,到底是詐尸還是另有隱情办绝,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布姚淆,位于F島的核電站孕蝉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏肉盹。R本人自食惡果不足惜昔驱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望上忍。 院中可真熱鬧骤肛,春花似錦、人聲如沸窍蓝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吓笙。三九已至淑玫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背絮蒿。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工尊搬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人土涝。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓佛寿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親但壮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子冀泻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355