Window是什么?
1.先看官方的定义:
1 | /** |
2.文档解释比较简单,其实就是一个抽象的管理类。当我们启动一个Activity
,生命周期开始时setContentView()
,都知道这个方法要传入即是我们的布局ID:
1 | public void setContentView(View view) { |
3.由于Window
是抽象类,而PhoneWindow
作为其唯一实现类,很好理解,这里即让Activity
与Window(PhoneWindow)
关联起来,这是第一步。
4.PhoneWindow
中的成员变量DecorView
,注释也给出了解释:This is the top-level view of the window, containing the window decor.
。DecorView
继承自FrameLayout,本质就是一个ViewGroup。为什么需要这个DecorView
?往前回忆setContentView()
这个方法,在PhoneWindow
的重写方法中对DecorView
的初始化方法installDecor()
,在我们开发过程中,安卓系统默认为我们提供了一些Theme
主题,不同的主题对应了不同的资源布局文件。在初始化时,通过addView
为DecorView
中加入了一个view root
并且这个root
包含的就是开发者设置的主题信息对应的系统布局。root
是一个线性布局,包含了actionbar
与一个FrameLayout
,这个就是包含我们自身布局的最终容器。到这里Window
就和View
关联起来了。
5.总结一下:activity中调用的setContenView将window与activity相关联,而phonewindow作为window的唯一实现类,每个activity中包含一个phonewindow,phonewindow中又持有了decorview的实例。decorview作为一个viewgroup,通过addview添加了一个view(root),最终我们设置的布局会被添加到这个root中的fagmelayout中。这样,activity就与view相关联了起来。window作为管理器的角色。包括view的添加移除,但是这些操作要借助另一个重要的类windowManager。
Window是否多余?
1.经过分析,发现window所包含的一些作用其实view基本都已经涵盖了,那么这个window是否多余呢?答案是否定的,类比MVC,MVP,MVVM
等设计模式,window的作用也很类似,使activity与view解耦。view本身代码量很大,处理的事情很多。另外window的添加涉及到IPC的调用处理,再来看看WindowManager这个接口,继承了viewmanager:
1 | /** Interface to let you add and remove child views to an Activity. To get an instance |
Dialog的context
1.看一段代码:
1 | Dialog dialog = new Dialog(getApplicationContext()); |
2.看看dialog的构造方法:
1 | Dialog(int themeResId, boolean createContextThemeWrapper) { Context context, |
3.mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
假设我们传入的是activity的context,那么得到的是activity的windowManager:
1 |
|
看windowManager的实现类WindowManagerImpl,其中包含成员变量private IBinder mDefaultToken;
很明显这个token指向的就是我们的activity,因此传入activity而实例化的dialog自然不会报token null is not valid这个错误。
4.现在看dialog中的show方法,解释为什么application类型的context会报错:
1 | public void show() { |
5.看windowmanagerimpl中两个关键方法:
1 | private IBinder mDefaultToken; |
系统电量低“弹窗”?
1.作为一个系统的全局“弹窗”,如果真的是dialog,那么上述分析就是错误,因为这个“弹窗”不依赖任何activity。下面是构造方法:
1 |
|