比較Activity和Dialog的窗口添加流程

之前在我的這篇blog中寫到了Activity啓動時activity / window /view之間的關係。大概的流程是,先創建activity,然後attach中執行window創建,接着setContentView中創建DecorView並且將DecorView和window進行綁定,接着在resume過程中通過將decorView添加到windowManager中WindowManager.addView(decor),在addView()方法中會創建ViewRootImpl供wm管理View樹,在addView()的末尾會調用root.addView(decorView)最終將界面呈現出來。

Activity創建窗口顯示過程

在這裏插入圖片描述

Dialog窗口添加流程

  • dialog創建
    • new Context
    • new Window(順帶創建了DecorView)
  • dialog.show()
    • dispatchOncreate()
    • onStart()
    • WM.addView()後面和Activity一樣

另外,這裏有一批總結性的文章可以參考下
https://www.jianshu.com/p/a50cbdeb1880

Android窗口類型

除了上面的Activity / Dialog(包括AlertDialog)外,Android還爲我們提供了PopUpWindow,Toast等形式的彈框,這些彈框最後的展示都是通過調用wm.addView()來展示的。我們也可以自定義彈框,前面創建View,定義好窗口的LayoutParams,設置好窗口type,最後也可以通過wm.addView()來展示窗口。在這些窗口展示過程過,我們可能會遇到窗口添加失敗的場景,這些失敗在ViewRootImpl的setView()方法中都拋出了對應異常,提供給開發者debug信息。如下圖所示:
添加view失敗場景
分析上述常見錯誤之前,先來了解下android wm管理的窗口類型。Android將窗口分爲三類:

  • Application window (應用窗口類型) 1~99
  • Sub-window(子窗口) 1000~1999
  • System window(系統窗口) 2000~2999

這三類窗口按照優先級從大到小,type越大,表示權限越高,能覆蓋在其他type之上。
在這裏插入圖片描述
結合上面兩張圖,可以找到我們平時遇到的window添加失敗的原因。

  1. 很多時候activity消失後彈框就會出現no token的情況,這個時候的做法是,dialog.show()之前判斷activity是否已經或者正在finish(),如果是,此時不要彈出dialog(或者toast),避免crash。
  2. 自定義全局彈窗時,彈框與activity token無關,可以將dialog彈框type設置爲系統彈框,如TYPE_APPLICATION_OVERLAY(6.0之後)/SYSTEM_ALERT_WINDOW(6.0之前),同時彈框之前需要動態請求SYSTEM_ALERT_WINDOW權限,否則會爆出權限錯誤。

窗口類型對應關係

窗口 類型
Activity TYPE_APPLICATION
Dialog TYPE_APPLICATION
PopUpWindow TYPE_APPLICATION_PANEL
Toast TYPE_TOAST

一張圖概況下這幾種窗口的區別,來源
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章