比较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

一张图概况下这几种窗口的区别,来源
在这里插入图片描述

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