Android 进阶解密阅读笔记9
新年开工第一天就是干!前面学习整理了系统,应用进程及四大组件的启动过程,接下来是从另外一个模块开始学习。与 AMS 相似,WMS 也涉及到很多知识点,先理解 WindowManager,为后面的 WindowManagerService 做准备。
WindowManager
WindowManager 是个接口,形容了少量和 Window 相关的行为。一个 WindowManager 实例和一个特定的 Display 相关联的( Display 可以了解为屏幕,实际就是一个用于显示的数据对象)。假如说已知 Display 对象,那么可以通过 Context 的方法 createDisplayContext 来获取相关联的 Context 对象,而后再调用 getSystemService(Context.WINDOW_SERVICE) 来获取相关联的 WindowManager 对象。
WindowManager 继承自 ViewManager,后者是用来管理 View 的,即 View 的增,删,改操作,所以前者也就同样有对 View 管理的功能。而 WindowManager 从字面上看是对 Window 进行管理,那么 Window 又是怎样个定义?
Window
Window 是个笼统类,形容了一个顶层视窗以及相关的行为。它的实例应该说作为一个顶层 View 被增加到 WindowManager 里,我们常说视图树,所以 Window 实例可以了解为 WindowManager 管理的根 View。这个根 View 规范了 UI 展现(例如就是手机屏幕上显示的区域)包括背景啊,标题栏范围啊,默认按键解决等等。
Android 对 Window 的实现类就是 PhoneWindow。
还是从启动 Activity 说起
启动 Activity 的过程中最后会走到 ActivityThread 的 performLaunchActivity 方法来创立 Activity,
//ActivityThreadprivate Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ContextImpl appContext = createBaseContextForActivity(r); Activity activity = null; try { java.lang.ClassLoader cl = appContext.getClassLoader(); activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent); } if (activity != null) { appContext.setOuterContext(activity); //这个 attach 方法之前在分析 mBase 变量赋值时分析过。 activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback,r.assistToken); }}//Activityfinal void attach(Context context, ActivityThread aThread,Instrumentation instr, IBinder token, int ident,Application application, Intent intent, ActivityInfo info,CharSequence title, Activity parent, String id,NonConfigurationInstances lastNonConfigurationInstances,Configuration config, String referrer, IVoiceInteractor voiceInteractor,Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) { attachBaseContext(context); //mWindow 就是 Window 类型,右边通过 PhoneWindow 进行实例化 //入参的 window 是指之前保存的 Window 实例,这里我们假设没有保存过,是新创立的 mWindow = new PhoneWindow(this, window, activityConfigCallback); //这句实现了 Window 与 WindowManager 对象的关联。 mWindow.setWindowManager((WindowManager)context.getSystemService( Context.WINDOW_SERVICE),mToken, mComponent.flattenToString(),(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); //在前面设置 WindowManager 之后,取得 WindowManager 对象引用 mWindowManager = mWindow.getWindowManager();}//Windowpublic void setWindowManager(WindowManager wm, IBinder appToken, String appName,boolean hardwareAccelerated) { mAppToken = appToken; mAppName = appName; mHardwareAccelerated = hardwareAccelerated; if (wm == null) { //通过 getSystemService 的方式确保 wm 一定不为 null wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); } //对 WindowManager 类型的 wm 进行强转后,调用方法并返回 WindowManager mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);}mContext.getSystemService(Context.WINDOW_SERVICE) 实际上调用的是 ContextImpl 的方法,内部的逻辑实际上是通过 SystemServiceRegistry 类在初始化静态语句块时提前注册好少量服务,例如 ACTIVITY_SERVICE, AUDIO_SERVICE, WINDOW_SERVICE 都在这里注册。完了之后,ContextImpl 对象会先从自己的缓存数组中获取指定服务,若发现没有就会创立,并缓存。这里需要 WINDOW_SERVICE,就创立了 WindowManagerImpl 对象。作为 WindowManager 返回了,所以后面能强制转换为 WindowManagerImpl。
createLocalWindowManager 方法内部其实是 new 了一个 WindowManagerImpl 对象,区别在于这个对象和当前这个 PhoneWindow 对象有了关联,我的了解是,通过 getSystemService 获取到的仅作为创立具体有效 WindowManager 使用,而不会用于管理具体的 Window。
这样一来,Window 具体化为 PhoneWindow 对象,WindowManager 也具体化为 WindowManagerImpl 对象,并做了关联,至于 Display,则是通过 WindowManagerImpl 对象中的 Context 变量来建立关联的。
WindowManagerImpl
根据前面这么一套分析,WindowManagerImpl 对象中的 Context 变量实际就是创立 Activity 时的 ContextImpl 对象,另外要留意的就是 WindowManagerGlobal 类型的对象。
还有 Window 属性
WindowManager 里有个静态内部类 LayoutParams 用来形容 Window 的属性,它继承自 ViewGroup 里的静态内部类 LayoutParams,后者用于告诉父 View 该如何布局展现自己。所以 WindowManager 的 LayoutParams 大体也是如此。但有几个特殊属性要关注。
- type
窗口类型属性,主要分为三大类,1.应用窗口,这类窗口就是平时使用最多的 Activity,数值范围 [1, 99]。 2.子窗口,需要依附于应用窗口,数值范围 [1000, 1999]。3.系统窗口,这个只有系统能用,我们用不了,数值范围 [2000, 2999]。数值越大,越显示在上层,所以系统窗口才会那么大的值,由于系统的窗口往往都是比较重要的内容展现或者者提示。 - flags
这个用于控制窗口的显示模式,用的不多,但其中有个值应该用的很多,FLAG_FULLSCREEN,表示全屏显示窗口。 - softInputMode
用来控制软键盘窗口与其余窗口的叠加展现,例如弹起软键盘后能否需要遮挡当前窗口,或者者上移,或者者甚至不展现软键盘等。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Android 进阶解密阅读笔记9