WindowManager体系总结

    WindowManager是Android中一个比较复杂的知识体系,今天来总结总结这方面的体系知识,为了便于理解,文章会使用通俗易懂的语言结合XMind图和一些源码进行一步步分析。

一、Window、WindowManager和WMS关系

    Window是这三者的核心,起到了桥梁的作用,她是一个抽象类,主要定义了一些对Window操作的抽象方法。WindowManager主要是管理Window是一个接口类,他继承自ViewManager接口,主要定义了一些对View的操作和一些常量,例如:添加View,移除View,删除View。WMS是WindowManagerServer的缩写,主要是连接WindowManager与Window之间的Binder的通信,即WindowManager通过WMS操作Window。


二、Window的属性

    Window的属性是指Window怎样通过WMS管理Window,这些管理的规则被定义在被定义在WindowManager的内部类LayoutParams中,了解Window的属性能够更好的理解WMS的内部原理。这里主要介绍Window的类型,Window的Flag,Window的软键盘相关模式三大内容。

1、Window的类型

    Window的类型大致包括三类,应用程序窗口,子窗口,系统窗口。每个大类又包含了很多种类型,它们都定义在WindowManager的静态内部类LayoutParams中。接下来对这三种窗口类型进行说明。

    (1)应用程序窗口:对应一个Activity,作用于Activity内部,在WindowManager定义了应用程序窗口TYPE值得类型范围1到99,数值越大说明该Window的等级越高,越在上面显示。
    (2)子窗口:不能独立的存在,必须依附于任何类型的父窗口。例如Dialog等,子窗口的TYPE值范围是1000到1999。
    (3)系统窗口:系统窗口的等级最高为,TYPE值范围为2000到2999。例如Toast、入法窗口、状态栏、系统错误窗口等等。

    注意:窗口可以叠加,显示次序根据TYPE值得顺序排列,依次为:系统窗口,子窗口,应用程序窗口。高的等级可以覆盖低的等级。

2、Window的标志

    Window的标志也就是Flag,用于控制Window的显示,同样被定义在WindowManager的内部类LayoutParams中,包括了很多种这里不进行一一列举了,设置通过通过Window的addFlags方法设置:

    (1)方法一

     window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏

    (2)方法二

    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

    注意:一般的弹窗需要依附于activity,在activity中弹窗可以不用设置flag,依附于应用程序窗口。但是在服务、广播中没有父窗口可以依附。所以不能简单使用这种方式,需要采用系统的弹窗,他的优先级很高,覆盖于应用界面的最高层,并且要设置setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT),否则会崩溃。

3、Window的软键盘相关模式

    Android中窗口与窗口的叠加死很常见的,但是如果叠加的是软键盘很可能就遮盖住了输入框,导致无法输入,这种体验是很差的这时候就需要设置Window的软键盘模式。有两种设置方式,一种是在清单文件Activity中设置,另一种是在代码里面进行设置。

    (1)android:windowSoftInputMode="stateVisible|adjustResize"

    (2)getWindow().setSoftInputMode(WindowManager.LayoutParams.

SOFT_INPUT_ADJUST_PAN);

      各输入模式的值含义:

       stateUnspecified:软键盘的状态并没有指定,系统将选择一个合适的状态或依赖于主题的设置

       stateUnchanged:当这个activity出现时,软键盘将一直保持在上一个activity里的状态,无论是隐藏还是显示

       stateHidden:用户选择activity时,软键盘总是被隐藏

       stateAlwaysHidden:当该Activity主窗口获取焦点时,软键盘也总是被隐藏的

       stateVisible:软键盘通常是可见的

       stateAlwaysVisible:用户选择activity时,软键盘总是显示的状态

       adjustUnspecified:默认设置,通常由系统自行决定是隐藏还是显示

       adjustResize:该Activity总是调整屏幕的大小以便留出软键盘的空间

       adjustPan:当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分


三、Window的添加过程

    WindowManager对Window的操作包括添加、更新、删除三个过程,他是一个接口继承自ViewManager,通过WMS进行操作。

    public interface ViewManager {
        void addView(View var1, LayoutParams var2);

        void updateViewLayout(View var1, LayoutParams var2);

        void removeView(View var1);
    }

    这个操作包含了两大部分一个是WindowManager的操作过程,另一个是WMS的操作过程,对于应用程序窗口,子窗口,系统窗口的窗口添加过程会有所不同,但是对于WMS处理部分,添加的过程基本上是一样的。


    WindowManager操作Window实际上是对View的操作,这个过程是通过实现类WindowManagerImpl,添加View是通过addView方法进行添加的,这个类在 /frameworks/base/core/java/android/view/WindowManagerImpl.java下,如下:

    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }

    可以看出Window的添加过程是通过WindowManagerGlobal进行操作的,WindowManagerImpl并没有涉及到实际的操作。找到/frameworks/base/core/java/android/view/WindowManagerGlobal.java这个类中的addView方法,源码比较长,不贴出来了可以看出主要做了如下:

    1、检验传入参数的完整性,并作出调整。

		if (view == null) {
			throw new IllegalArgumentException("view must not be null");
		}
		if (display == null) {
			throw new IllegalArgumentException("display must not be null");
		}
		if (!(params instanceof WindowManager.LayoutParams)) {
			throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
		}

		final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
		if (parentWindow != null) {
			parentWindow.adjustLayoutParamsForSubWindow(wparams);
		} else {
		....................................省略部分代码...................................
		}

   2、创建ViewRootImpl集合,并且添加View。

		private final ArrayList<View> mViews = new ArrayList<View>();
		private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
		private final ArrayList<WindowManager.LayoutParams> mParams =new ArrayList<WindowManager.LayoutParams>();
		private final ArraySet<View> mDyingViews = new ArraySet<View>();
		..........................................分割线............................................
		mViews.add(view);
		mRoots.add(root);
		mParams.add(wparams);

    3、通过ViewRootImpl的setView调用requestLayout更新界面,最终会调用WindowSession的addToDisplay方法进行绘制,他的内部会调用WMS完成添加。源码地址/frameworks/base/core/java/android/view/ViewRootImpl.java。

(1)View的绘制

        @Override
        public void requestLayout() {
            if (!mHandlingLayoutInLayoutRequest) {
                checkThread();
                mLayoutRequested = true;
                //View的绘制入口
                scheduleTraversals();
            }
        }

(2)View的添加

        res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                getHostVisibility(), mDisplay.getDisplayId(),
                mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                mAttachInfo.mOutsets, mInputChannel);

   mWindowSession是一个AIDL文件,定义了很多IPC通信通信接口,文件地址/frameworks/base/core/java/android/view/IWindowSession.aidl,真正的实现类是Session类。这个类位于/frameworks/base/services/core/java/com/android/server/wm/Session.java

        @Override
        public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
                int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
                Rect outOutsets, InputChannel outInputChannel) {
            return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                    outContentInsets, outStableInsets, outOutsets, outInputChannel);
        }

        上面的mService就是WindowManagerService,这样一来,Window的添加请求就会从这交给WMS处理了。至此Window的添加过程分析结束。以上就是Window的添加过程的主要流程,更新和删除和这个类似,这里不再做分析了。


注:转载请注明,尊重他人的劳动成果。


<think>好的,用户现在要我介绍一下Android的体系结构。我需要先回忆一下相关知识,确保准确。Android体系结构通常分为几个层次,可能包括Linux内核、库运行时、应用框架以及应用层这些部分。 用户之前问过关于AndroidManifest.xml中重复定义MAIN action的问题,这说明他对Android开发有一定了解,可能是个开发者或者正在学习。因此,回答时要保持技术性,但也要清晰易懂,避免过于复杂。 接下来,我需要确认Android体系结构的标准分层。记得官方文档里提到的是四层结构:Linux内核、硬件抽象层(HAL)、原生库Android运行时、应用框架,最后是应用层。不过有时候不同的资料会有不同的分法,比如有的可能把HAL包含在Linux内核层里,或者单独列出来。 用户的问题是要“简述”,所以需要简明扼要,不需要太深入每个部分的细节。但可能需要每个层次的关键组件作用。比如Linux内核负责驱动硬件交互,应用框架提供API给开发者,应用层就是用户看到的APP。 还要注意用户可能关心各个层次之间的关系,或者每个层次的具体例子,比如运行时环境是ART,库包括OpenGL、SQLite等。应用框架里的Activity Manager、Content Providers这些组件也很重要。 需要避免错误,比如确保运行时环境现在是ART而不是Dalvik,虽然Dalvik之前被使用过,但现在已经被替代。同时,HAL层的作用是提供标准接口给硬件厂商,这样不同的硬件可以实现统一的接口,便于维护升级。 结构上,可能先总述体系结构分为几个层次,再分点介绍每个层次,最后总结各层之间的关系。使用例子会让解释更清晰,比如应用开发者使用应用框架的API来构建应用,而应用框架又依赖于底层的库运行时环境。 另外,用户之前的问题涉及到Manifest文件,可能对应用层框架层的交互比较感兴趣,所以在介绍应用框架时可以提到组件如Activity、Service等,这些都是在应用框架层定义的,并通过Manifest注册。 最后需要检查是否有遗漏的部分,比如系统应用是否属于应用层,HAL是否应该单独作为一层。根据最新的Android文档,HAL确实是独立的一层,所以应该包括进去。确保信息准确,避免过时的内容。 总结思考:回答需要结构清晰,层次分明,每个部分简明扼要,涵盖Linux内核、硬件抽象层、系统运行库Android运行时、应用框架层以及应用层,并说明各层的作用关键组件,同时使用例子帮助理解。</think>### Android 体系结构(分层架构) #### 1. **Linux 内核层** - **核心作用**:硬件抽象与基础驱动 - 提供硬件驱动(显示/摄像头/蓝牙等) - 管理进程调度、内存管理等操作系统基础功能 - 安全性支持(如 SE Linux) #### 2. **硬件抽象层 (HAL)** - **关键特性**:标准化硬件接口 - 定义硬件模块的标准接口(如 `hardware/libhardware`) - 允许硬件厂商实现定制驱动而不影响上层架构 - 示例模块:传感器 HAL、相机 HAL #### 3. **系统运行库层** - **Native 库** - OpenGL ES:3D 图形渲染 - SQLite:轻量级数据库 - WebKit:浏览器引擎基础 - **Android 运行时** - **ART (Android Runtime)**:取代 Dalvik 的新运行时 - 采用 AOT (Ahead-Of-Time) 编译提升性能 - 支持 DEX 字节码执行 #### 4. **应用框架层** - **核心服务组件** | 组件类型 | 功能说明 | |-------------------|-----------------------------| | Activity Manager | 管理应用生命周期 | | Content Providers | 跨应用数据共享 | | View System | UI 控件管理与事件分发 | | Notification Mgr | 系统通知管理 | - **关键 API** - 提供四大组件(Activity/Service/Broadcast/ContentProvider) - 系统服务(如 WindowManager/PackageManager) #### 5. **应用层** - **直接可见层** - 用户安装的第三方应用(如微信、支付宝) - 系统预装应用(设置、电话、短信) ### 架构交互示例 1. **用户点击应用图标** → 通过 **应用框架层** 的 `ActivityManager` 启动进程 2. **相机拍照请求** → 通过 **HAL** 调用硬件驱动 3. **SQLite 数据库操作** → 使用 **Native 库** 的 C/C++ 实现 ### 最新演进 - **Project Treble**:通过 `Vendor Interface` 分离 HAL 与系统更新 - **Kotlin 优先**:应用层开发语言趋势变化 该分层架构实现了硬件无关性(*Hardware Abstraction*)与开发灵活性,使 Android 能适配不同设备形态(手机/电视/车载系统)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值