Android之WindowManager介绍

2023-05-16

WindowManager

android中真正展示给用户的是window和view.

activity在android中所其的作用主要是处理一些逻辑问题,比如生命周期的管理、建立窗口等。

在android中,窗口的管理还是比较重要的一块,因为他直接负责把内容展示给用户,并和用户进行交互。响应用户的输入等。

WindowManager继承自ViewManager,里面涉及到窗口管理的三个重要方法,分别是:
* addView();
* updateViewLayout();
* removeView();

Window

android的窗口分为三种:
1、应用程序窗口 (Application Window): 包括所有应用程序自己创建的窗口,以及在应用起来之前系统负责显示的窗口。
2、子窗口(Sub Window):比如应用自定义的对话框,或者输入法窗口,子窗口必须依附于某个应用窗口(设置相同的token)。
3、系统窗口(System Window): 系统设计的,不依附于任何应用的窗口,比如说,状态栏(Status Bar), 导航栏(Navigation Bar), 壁纸(Wallpaper), 来电显示窗口(Phone),锁屏窗口(KeyGuard), 信息提示窗口(Toast), 音量调整窗口,鼠标光标等等。


 Window.java是个虚类:

public abstract class Window {}

他的具体实现是 PhoneWindow.java 。

PhoneWindow对象被创建是在Activity中:

    final 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) {
        attachBaseContext(context);
        ……

        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
             ……

        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        ……
    }

 代码中会调用PhoneWindow的setWindowManager函数(实现在Windows类中):

    public void setWindowManager(WindowManager wm, IBinder appToken, String appName) {
        setWindowManager(wm, appToken, appName, false);
    }

    public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
        mAppToken = appToken;
        mAppName = appName;
        mHardwareAccelerated = hardwareAccelerated
                || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
        if (wm == null) {
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        }
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }

这里看到会执行WindowManagerImpl.java的createLocalWindowManager函数:

    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
        return new WindowManagerImpl(mContext, parentWindow);
    }

所以最后mWindowManager 保存了一个local的WindowManager.

之前传进来的WindowManagerImpl实例又去创建了一个具有ParentWindow的WindowManagerImpl实例,根据他的参数可以看出,这里的Window是作为WindowManagerImpl的parentWindow的,也就是他们俩的关系从表面看上去好像是父级和子级的层级关系。

WindowManager的功能介绍

Window是一个抽象的概念,每一个Window都对应着一个View和一个ViewRootImpl,Window和View通过ViewRootImpl来建立联系,说明View才是Window存在的实体,在实际使用中无法直接访问Window,对Window的访问必须通过WindowManager。

Window的添加过程需要通过WindowManager的addView来实现,WindowManager是一个接口,它的真正实现是WindowManagerImpl类。

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

mGlobal是WindowManagerGlobal:

private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

WindowManager操作Window,不过具体的实现细节还是WindowManagerGlobal这个类来做的,这个类是一个单例模式。

继续看下WindowManagerGlobal.java的addView函数:

    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        ……

        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
        if (parentWindow != null) {
            // 界面布局的限制
            parentWindow.adjustLayoutParamsForSubWindow(wparams);
        } else {
            final Context context = view.getContext();
            if (context != null
                    && (context.getApplicationInfo().flags
                            & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
                wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
            }
        }

        ViewRootImpl root;
        View panelParentView = null;

        synchronized (mLock) {
             ……
            // 构建界面控制
            root = new ViewRootImpl(view.getContext(), display);

            view.setLayoutParams(wparams);

            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);

            try {
                //将View显示到手机窗口
                root.setView(view, wparams, panelParentView);
            } catch (RuntimeException e) {
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }

其中创建了ViewRootImpl 。

ViewRootImpl 是一个视图层次结构的顶部,ViewRootImpl 实现了 View 与 WindowManager 之间所需要的协议,作为 WindowManagerGlobal 中大部分的内部实现。

在 WindowManagerGlobal 中实现方法中,都可以见到 ViewRootImpl,也就说 WindowManagerGlobal 方法最后还是调用到了 ViewRootImpl。

比如addView,removeView,update 的调用顺序:WindowManagerImpl -> WindowManagerGlobal -> ViewRootImpl.

而且WindowManager.java 是继承的ViewManager .

public interface WindowManager extends ViewManager {}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android之WindowManager介绍 的相关文章

随机推荐

  • UML流程图

    流程图介绍 流程图 xff08 FlowChart xff09 是描述我们进行某一项活动所遵循顺序的一种图示方法 它能通过图形符号形象的表示解决问题的步骤和程序 好的流程图 xff0c 不仅能对我们的程序设计起到作用 xff1b 在帮助理解
  • Android: 如何切换 SCO 链路

    最近在做蓝牙音箱开发 xff0c 在 A2DP 和 HFP 来回切换的时候 xff0c 遇到了手机兼容性的问题 最终发现设备收声和手机收声 xff0c 是因为 soc 切换有问题 原先在网上找了一些资料发现其实还蛮简单的 就两句话 xff0
  • Java 枚举(enum) 详解6种常见的用法

    用法一 xff1a 常量 在JDK1 5 之前 xff0c 我们定义常量都是 xff1a public static final 现在好了 xff0c 有了枚举 xff0c 可以把相关的常量分组到一个枚举类型里 xff0c 而且枚举提供了比
  • Android注解快速入门和实用解析

    首先什么是注解 xff1f 64 Override就是注解 xff0c 它的作用是 xff1a 1 检查是否正确的重写了父类中的方法 2 标明代码 xff0c 这是一个重写的方法 1 体现在于 xff1a 检查子类重写的方法名与参数类型是否
  • Android高版本Service在后台一分钟被杀死

    最近公司出现了一个Bug xff0c Service在后台写log时候一分钟左右被杀死 xff0c 或者运行一会就被杀死了 xff0c 上网搜了一下原来是Android高版本为了保护电量 xff0c 流量什么的 xff0c 会在后台杀死这些
  • 解决Android8.0之后开启service

    背景 项目测试时发现的 xff0c 在双击返回键关闭应用后 xff08 并未杀死后台 xff09 重新打开APP xff0c 其他手机都OK xff0c 但是8 0的手机会出现较频繁的crash 检查代码 xff0c 问题锁定在重新开启应用
  • 在Android Studio中使用Lambda

    应用场景 在使用过程中 xff0c 不建议在自定义接口中使用 xff0c 原因是因为Lambda常应用在只有一个方法的接口中 而我们自定义的接口 xff0c 后期可能会增加接口中的方法 xff0c 这样修改的地方就比较多 xff0c 因为L
  • Android枚举实现Parcelable接口

    枚举类实现Parcelable的写法如下 xff1a public enum MyEnum implements Parcelable FIRST 1 SECOND 2 private int mValue MyEnum int value
  • Android Studio Build Output控制台输出乱码解决

    Android Studio版本升级到4 0之后 xff0c 出现Build Output控制台输出乱码的现象 该情况在Android Studio版本3 6及以上就会出现 解决方法 xff1a 点击Android Studio 菜单栏He
  • 1230---KVM Windows 虚拟机磁盘如何快速扩容

    KVM Windows 虚拟机磁盘如何快速扩容 前言 xff1a 由于KVM虚拟机直接构建于宿主机内核之上 xff0c 对于充分利用宿主机硬件性能有天然的优势 网上针对KVM Linux 虚拟机运维的文章很多 xff0c 但针对KVM Wi
  • Android中的IPv6

    什么是IPv6 IPv6 的全称是Internet Protocol version 6 Internet Protocol 译为 互联网协议 xff0c 所以 IPv6 就是互联网协议第6版 它对比于 IPv4 所带来的是地址池的扩容 x
  • 浅谈Android下的注解

    什么是注解 java lang annotation xff0c 接口 Annotation xff0c 在JDK5 0及以后版本引入 注解是代码里的特殊标记 xff0c 这些标记可以在编译 类加载 运行时被读取 xff0c 并执行相应的处
  • 浅析Java中的final关键字

    一 final关键字的基本用法 在Java中 xff0c final关键字可以用来修饰类 方法和变量 xff08 包括成员变量和局部变量 xff09 下面就从这三个方面来了解一下final关键字的基本用法 1 修饰类 当用final修饰一个
  • volatile与Java内存模型

    1 volatile特点 volatile的两大特点是可见性和有序性 xff1b volatile的内存语义 xff1a 当写一个volatile变量时 xff0c JMM会把该线程对应的本地内存中的共享变量值立即刷新回主内存中 当读一个v
  • 隐藏Detected problems with API compatibility警告弹窗

    如果在Android9 0亦即API 28或以上的系统中运行debug app时 xff0c 出现如下警告弹窗 xff1a Detected problems with API compatibility visit g co dev ap
  • JAVA中枚举如何保证线程安全

    枚举类型到底是什么类呢 xff1f 是enum吗 xff1f 明显不是 xff0c enum就和class一样 xff0c 只是一个关键字 xff0c 他并不是一个类 xff0c 那么枚举是由什么类维护的呢 xff0c 首先写一个简单的枚举
  • ‘sed‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

    在使用adb命令查看task和Activity的时候 xff0c 发现报错 sed 不是内部或外部命令 xff0c 也不是可运行的程序 或批处理文件 看样子是没有配置sed的环境变量 xff0c 或者没有sed工具 从网上找了一下 xff0
  • win11 我们无法设置移动热点

    有可能是因为Windows移动热点服务被禁用 启动移动热点服务 1 使用该配件的键 43 热键启动运行 WindowsR 2 要打开 服务 xff0c 请在 打开 框中键入此文本并单击 确定 xff1a services msc 3 选中W
  • 链栈(java 实现)

    Node类 xff1a package LinkStack public class Node String name int age Node next public Node public Node String name int ag
  • Android之WindowManager介绍

    WindowManager android中真正展示给用户的是window和view activity在android中所其的作用主要是处理一些逻辑问题 xff0c 比如生命周期的管理 建立窗口等 在android中 xff0c 窗口的管理