在Activity布局加载流程源码分析(I)文章中,已经详细分析了setContentView()加载流程,但对于装饰器DecorView怎么被加载到Window上的,上篇博文没有说到,所以本篇博文将会接着上篇博文,继续分析Activity布局的加载流程。
在开始分析之前,我们需要了解一些概念,如:
- Window: 是一个抽象类,表示是一个窗口。Android系统中的界面,也都是以窗口的形式存在的。
- PhoneWindow: 是Window类具体实现类,Activity中布局加载逻辑主要就是在此类中完成的。
- DecorView:是PhoneWindow中的一个内部类,也是Window的顶级View,主要负责装载各种View。
- WindowManager: 是Window的管理类,管理着Window的添加、更新和删除。
- WindowManagerService(AMS):是系统窗口管理服务类,具体管理着系统各种各样的Window。
- ViewRootImpl:是View的绘制的辅助类,所有View的绘制都离不开ViewRootImpl。
一、Activity布局及DecorView加载分析
这里,我们接着Activity布局加载流程继续分析。在布局加载流程最后,主要是通过WindowManager添加装饰器DecorView到Window中,从而实现Activity布局的加载,这里继续来看那部分代码
|
|
这里,简单解释一下参数。其中r.window为PhoneWindow,decor就是装饰器DecorView,wm就是WindowManager。最后通过wm.addView(decor, l)方法,实现Activity布局的加载。这里还注意到WindowManager.LayoutParams的type参数为WindowManager.LayoutParams.TYPE_BASE_APPLICATION,也即是应用窗口类型(所有程序窗口的base窗口,其他应用程序窗口都显示在它上面),具体有关Window的窗口属性,可以参考博文Android悬浮窗原理解析(Window),想了解的同学,可以点击看看,这里有比较全的Window属性解释。
我们再来看一下wm,这里定义的类型是接口ViewManager,其实它就是WindowManager,这里主要是使用设计模式的里氏替换原则(源码中很多地方都用这原则)。wm主要是通过a.getWindowManager()赋值的,所以我们主要来看看Activity中的getWindowManager()方法
mWindowMananger是Activity的一个属性变量,通过Activity的启动加载流程,Activity初始化过程中就会对mWindowManager进行赋值,而Activity初始化主要通过attach方法完成,所以我们继续来看Activity的attach方法
这里是通过mWindow.getWindowManager()来赋值mWindowManager,而mWindow即PhoneWindow,这点在Activity布局加载流程中,已分析过。由于PhoneWindow是继承至Window,通过阅读源码分析知道,getWindowManager()方法,主要是window中完成实现的,所以我们具体来看看Window中的getWindowManager()方法
这里,我们先来看一下注释1,WindowManagerImpl.getDefault(),这很明显是单例模式。我们继续来看看源码
这里wm就是WindowManagerImpl。我们来看看WindowManagerImpl类
我们再来看看注释2,也即LocalWindowManager类
我们继续来看看LocalWindowManager类继承的WindowManagerImpl的内部类CompatModeWrapper
WindowManagerImpl的内部类CompatModeWrapper实现了WindowManager接口,而WindowManager又实现了ViewManager接口
我们来看看ViewManager接口
这里实现ViewManager接口的有WindowManager,而WindowManagerImpl和CompatModeWrapper也都实现WindowManager接口,从而间接实现了ViewManager接口,也都实现的添加,更新和删除View的方法。
所以,在最开始处,以ViewManager定义的wm其实也就是LocalWindowManager,通过相互继承调用,其实最后调用的是WindowManagerImpl中的addView()方法,我们继续来看看此方法
这里有三个数组mViews,mRoots,mParams变量,mViews主要保存向Window中添加的View,mRoots主要保存实现绘制View的ViewRootImpl,mParams主要保存添加的Window参数,最后每一个添加的View都会调用root.setView(view, wparams, panelParentView)方法,实现View的绘制。关于这三个参数的作用,是因为WindowManager中可能添加多个Window,多个View,所以需要保存起来,方便删除和更新。
关于WindowManagerImpl的源码,这里需要注意一下,由于我用的版本是Andorid4.1.1_r1,源码如上,而在大于Andorid4.1.1_r11的版本,如Android5.1.1中的WindowManagerImpl源码的addView方法,主要是通过WindowManagerGlobal来实现的,逻辑也都和Andorid4.1.1_r1一样,只是把部分逻辑封装成WindowManagerGlobal,这里我就不多说,想了解的同学,可以自行查看。
到这里,DecorView添加入Window的流程就分析完了。接下来主要就是DecorView的绘制流程,也即View的绘制流程。
注:源码采用android-4.1.1_r1版本,建议下载源码然后自己走一遍流程,这样更能加深理解。