我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android窗口机制

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android窗口机制

DecorView通过PhoneWindow与WindowManagerService通信原理图

在这里插入图片描述

每个Activity都有一个Window对象,这个对象是PhoneWindow类型的。
每个Window对象里面都维护着一个WindowManager对象。

Activity里面添加一个View是通过WindowManager的addView()方法实现的

相关关键类

WindowManagerService
高层级,系统窗口管理服务

Window
一个顶级窗口的外观和行为策略的一个抽象基类。

Window并不是真实存在的,它表示一种抽象的功能集合,View才是Android中的视图呈现形式,绘制到屏幕上的是View不是Window,但是View不能单独存在,它必需依附在Window这个抽象的概念上面,Android中需要依赖Window提供视图的有Activity,Dialog,Toast,PopupWindow,StatusBarWindow(系统状态栏),输入法窗口等,因此Activity,Dialog等都维护着一个Window对象。当我们调用Activity的setContentView()时,其实最终会调用Window的setContentView(),当我们调用Activity的findViewById()时,其实最终调用的是Window的findViewById()。
对 Window 的操作是通过 WindowManager 来完成的。

WindowManager
WindowManager是一个接口,里面常用的方法有:添加View,更新View和删除View,WindowManager继承自ViewManager,这三个方法定义在ViewManager中:

public interface ViewManager
{
    public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);
}

WindowManagerImpl
低层次,负责与系统窗口管理服务进行操作通信,与Context进行关联。
是WindowManager的实现类,大部分工作都通过WindowManagerGlobal来实现。
WindowManagerGlobal
低层次,负责与系统窗口管理服务进行操作通信,不与Context进行关联。

ViewRootImpl
ViewRootImpl是一个视图层次结构的顶部,它实现了View与WindowManager之间所需要的协议,作为WindowManagerGlobal中大部分的内部实现,也就说WindowManagerGlobal方法最后还是大部分调用了ViewRootImpl。
类似 ApplicationThread 负责跟AMS通信一样,ViewRootImpl 的一个重要职责就是跟 WMS 通信,它通过静态变量 sWindowSession(IWindowSession实例,在WindowManagerGlobal中创建)与 WMS 进行通信。

源码分析

ActivityThread.handleResumeActivity()方法 :

  @Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, String reason) {
    ...//其他代码
          if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                } else {
                    // The activity will get a callback for this {@link LayoutParams} change
                    // earlier. However, at that time the decor will not be set (this is set
                    // in this method), so no action will be taken. This call ensures the
                    // callback occurs with the decor set.
                    a.onWindowAttributesChanged(l);
                }
            }
    ...//其他代码
 }

调用WindowManagerImpl.addView() :

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

调用WindowManagerGlobal.addView():

    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        ...//其他代码
            root = new ViewRootImpl(view.getContext(), display);
            view.setLayoutParams(wparams);
            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);
            // do this last because it fires off messages to start doing things
            try {
                root.setView(view, wparams, panelParentView);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }

调用ViewRootImpl.java的setView方法

    
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
         		...//其他代码
                // Schedule the first layout -before- adding to the window
                // manager, to make sure we do the relayout before receiving
                // any other events from the system.
                requestLayout(); //请求布局
                if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                    mInputChannel = new InputChannel();
                }
                mForceDecorViewVisibility = (mWindowAttributes.privateFlags
                        & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
                } 
			    ...//其他代码
}

res = mWindowSession.addToDisplay() 调用了Session的addToDisplay()方法:

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

调用mService.addWindow()方法添加Window,这个mService其实就是WindowManagerService对象,也就是说布局最终是由 WindowManagerService 来添加的。
分析到这里可以看到,ViewRootImpl是通过 mWindowSession(来自WindowManagerGlobal的sWindowSession对象)和WindowManagerService通信的。

参考:
ViewManager、ViewRootImp、WindowManagerImpl、WindowSession等详细解析
Android窗口机制(一)——Window,PhoneWindow,DecorView理解
Window窗口机制(二)——Window,WindowManager理解
Window窗口机制(三)——WindowManager,ViewRootImpl,View理解
Android 窗口机制
Android窗口机制(四)ViewRootImpl与View和WindowManager
android WindowManagerService
Window, WindowManager和WindowManagerService之间的关系

android window(三)ViewRootImpl
ViewRootImpl的独白,我不是一个View(布局篇)

ViewRootImpl源码分析事件分发

面试进阶之窗口机制

https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/view/Window.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/view/WindowManagerImpl.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/view/WindowManagerGlobal.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/view/ViewRootImpl.java
http://androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/services/core/java/com/android/server/wm/Session.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java


作者:yzpyzp


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android窗口机制

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android窗口机制

DecorView通过PhoneWindow与WindowManagerService通信原理图每个Activity都有一个Window对象,这个对象是PhoneWindow类型的。 每个Window对象里面都维护着一个WindowMana
2022-06-06

Android手机悬浮窗口小案例

本文实例为大家分享了Android九宫格图片展示的具体代码,供大家参考,具体内容如下 –主页面——–//布局中就一个Button public class MainActivity extends Activity {@Overridepr
2022-06-06

Android N多窗口支持

Android N 可以同时显示多个应用窗口。 在手机上,两个应用可以在“分屏”模式中左右并排或上下并排显示。例如,用户可以 在上面窗口聊QQ,下面窗口发送短信。如图所示,两个app在分屏模式中上下显示:如何让你的app支持多窗口?如果你的
2023-05-31

android 窗口焦点介绍

背景 我们经常会遇到一种Application does not hava focused window的ANR异常,这种异常一般是没有焦点窗口FocusedWindow导致,且这类异常只会发生在key事件的派发,因为key事件是需要找到一
2023-08-21

结合Windows窗口深入分析Android窗口的实现

在Android中,窗口是一个基本的图形用户界面元素,它提供了一个屏幕区域来放置应用程序的用户界面元素。窗口可以是全屏的,也可以是一个小的对话框。每个窗口都有一个特定的主题和样式,可以根据应用程序的需求进行自定义
2023-05-16

JavaScript怎么定制新窗口

这篇文章主要介绍“JavaScript怎么定制新窗口”,在日常操作中,相信很多人在JavaScript怎么定制新窗口问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JavaScript怎么定制新窗口”的疑惑有所
2023-06-03

python怎么控制windows窗口

要控制Windows窗口,您可以使用`pywin32`库来与Windows API进行交互。首先,您需要安装`pywin32`库。可以使用以下命令来安装它:```pip install pywin32```接下来,您可以使用以下代码示例来控
2023-10-11

Android应用程序窗口(Activity)窗口对象(Window)创建指南

在前文中,我们分析了Android应用程序窗口的运行上下文环境的创建过程。由此可知,每一个Activity组件都有一个关联的ContextImpl对象,同时,它还关联有一个Window对象,用来描述一个具体的应用程序窗口。由此
2022-06-06

制作弹出公告窗口(转)

有时我们需要采用公告窗口来展示一些重要的信息,所谓公告窗口是指我们浏览主页时,随主页面的加载而自动弹出的小窗口,公告窗口中一般会放上新闻、布告的信息。下面我们看看怎样用几句简单的Javascript语句来实现它。方法一:在之间插入如下一段J
2023-06-03

html弹出窗口怎么制作

要制作 html 弹出窗口,需要使用 元素并设置 id、class 和 style 属性来创建弹出窗口容器。随后使用 javascript 的 window.open() 函数或其他参数(如 width 和 height)来显示弹出窗口。
html弹出窗口怎么制作
2024-05-21

Android弹出窗口实现方法

本文实例讲述了Android弹出窗口实现方法。分享给大家供大家参考,具体如下: 直接上代码:/** * 弹窗--新手指引 * @param cxt * @param id 资源编号 * @create_time 2011-7-27 下午0
2022-06-06

深入浅析Android接口回调机制

在使用接口回调的时候发现了一个经常犯的错误,就是回调函数里面的实现有可能是用多线程或者是异步任务去做的,这就会导致我们期望函数回调完毕去返回一个主函数的结果,实际发现是行不通的,因为如果回调是多线程的话你是无法和主函数同步的,也就是返回的数
2022-06-06

Android画中画窗口开启方法

Android8.0Oreo(APILevel26)允许活动启动画中画Picture-in-picture(PIP)模式。PIP是一种特殊类型的多窗口模式,主要用于视频播放。PIP模式已经可用于AndroidTV,而Android8.0则让该功能可进一步用于其他Android设备
2023-01-04

Android画中画窗口如何开启

这篇文章主要讲解了“Android画中画窗口如何开启”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Android画中画窗口如何开启”吧!基础画中画manifest 设置为了适配开启画中画状态
2023-07-04

android多窗口模式怎么实现

Android多窗口模式可以通过以下几个步骤实现:1. 在AndroidManifest.xml文件中声明`android:resizeableActivity="true"`属性,以允许应用程序在多窗口模式下运行。2. 在`onCreat
2023-09-18

深入理解Android之接口回调机制

刚开始学对于这个机制理解不够深刻,现在重新整理下思路。开发中,接口回调是我们经常用到的。 接口回调的意思即,注册之后并不立马执行,而在某个时机触发执行。首先解决啥是回调:举个例子:某天,我打电话向你请教问题,当然是个难题,你一时想不出解决方
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录