Android UI | DecorView 如何添加到Window 里面的

Android UI | DecorView 如何添加到Window 里面的,第1张

上一篇讲了 setContentView 到所有布局的加载: 传送门

要想了解DecorView 如何添加到Window里面的,需要先了解Activity如何运行的

这里就要提到一个类ActivityThread,这里面的一个方法

其中比较关键的方法是调用是:

activity.attach(...)方法,这个方法内容如下:

随后再来看看 ActivityThread类中的handleResumeActivity方法,方法内容如下:

继续查看 WindowManagerImpl里面的addView方法

继续查看 ViewRootImpl类里面的setView方法,如下:

到这里,decorView 添加到PhoneWindow 基本结束了。下面我们继续查看,view 是如何在RootViewImpl类中绘制出来的。

查看ViewRootImpl类里面的 requestLayout()方法

继续查看 mTraversalRunnable

继续查看 performMeasure

decorView 实际上继承了 ViewGroup 、 View ,所以实际上也是调用的View的measure方法。所以这些 measure 、 layout 、 draw都是再ViewRootImpl发起的。

到这里,Activity 启动过程中生成PhoneWindow , 并加载DecorView ,之后调起绘制流程。

总结:ActivityThread.handleResumeActivity中,wm.addView(decor, l)

把decorView 添加到windowManager , 然后在WindowManagerImpl 里面初始化了 ViewRootImpl ,然后调用 ViewRootImpl.setView(),在setview方法里调用了view.assignParent(this),将Decorview的mParent设置成ViewRootImpl

下面是比较严谨的获取方法:

- (UIWindow *)lastWindow

{

NSArray *windows = [UIApplication sharedApplication].windows

for(UIWindow *window in [windows reverseObjectEnumerator]) {

if ([window isKindOfClass:[UIWindow class]] &&

CGRectEqualToRect(window.bounds, [UIScreen mainScreen].bounds))

return window

}

return [UIApplication sharedApplication].keyWindow

}

Window 表示一个窗口,Android所有的视图,不管是Activity、Dialog、Toast,都是由Window来呈现的,Window是View的直接管理者,Window是一个抽象类,它的具体实现是PhoneWindow,每个Window都对应一个View和一个ViewRootImpl,Window和View通过ViewRootImpl来建立联系,可以说Window并不是实际存在的,它是以View的形式存在

WindowManager 创建Window,和WindowManagerService交互(IPC),我们常用WindowManager的功能有三个,分别是添加、更新、删除View,通过这三个方法我们可 创建一个Window并向其添加、更新、删除View

下面介绍下WindowManager的LayoutParams,它有两个属性很重要,一个是flags,代表Window的属性,另一个是type,代表Window的类型

常用的flags:

FLAG_NOT_FOCUSABLE :表示 Window不获取焦点,也不会接收各种输入事件 ,此标记会同时启用FLAG_NOT_TOUCH_MODAL,最终事件会直接传递到下面有焦点的Window

FLAG_NOT_TOUCH_MODAL :此标记模式下,Window内的点击事件由Window自己处理,Window外部的点击事件由下面的Window进行处理

FLAG_SHOW_WHEN_LOCKED :开启此模式可以让Window显示在锁屏界面上

type有 3种类型 ,分别是 应用窗口(1-99)、子窗口(1000-1999)、系统窗口(2000-2999),Window是分层的,层级越大的Window,就显示的越上面 ,常见的Dialog就是一个子窗口,而Toast和状态栏是系统窗口, 系统窗口是需要声明权限才能创建的

Window的addView实际实现是在WindowManagerImpl里,WindowManagerImpl里addView又会调用WindowManagerGlobal的addView方法,该方法内部会创建一个ViewRootImpl并将要添加的View、ViewRootImpl加进WindowManagerGlobal内部的几个列表里( 通过findViewLocked方法获取索引 ),然后调ViewRootImpl的setView更新界面并完成Window的添加过程(setView内部会调requestLayout->scheduleTravels注册下一帧刷新监听,requestLayout后会通过session调用一次IPC向WMS添加Window), 个人理解,屏幕上View的刷新都是通过ViewRootImpl来完成的,WMS只是负责Window的添加、删除,以便知道该向哪些Window分发事件

Activity实现了Window.Callback接口,而且Activity内部创建的PhoneWindow.setCallback(this),因此当Window接收到外界状态改变时,就会回调Activity的相关方法


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/bake/7986654.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-12
下一篇2023-04-12

发表评论

登录后才能评论

评论列表(0条)

    保存