Android 窗口管理 - 窗口添加过程分析Client端

一、窗口的三种形式

  1. Activity:独立的页面窗口,拥有完整生命周期。这种是最常用的方式。
  2. Dialog:对话框形式的窗口,依赖Activity上下文。
java 复制代码
Dialog dlg = new Dialog(context);
dlg.addContentView(makeView(), new LayoutParams(300, 400));
dlg.setCancelable(true);
dlg.setCanceledOnTouchOutside(true);
dlg.setOnDismissListener(new DialogInterface.OnDismissListener() {
    @Override
    public void onDismiss(DialogInterface dialog) {
        Looper.myLooper().quit();
    }
});
dlg.setTitle("Not Looper.getMainLooper() check");
dlg.show();

3.View:通过WindowManager.addView直接添加到系统中。系统中有很多窗口就是通过这种方式添加到系统中的。比如状态栏,虚拟导航条,小圆点啥的。第三方app也可以通过这种方式添加浮动窗口。

二、核心接口

  1. App获取IWindowManager接口

    WindowManager是接口类, WindowManagerImpl是WindowManager的实现。WindowManagerGlobal相当于WindowManagerImpl内部的代理,它才是真正和WMS通过IWindowManager通信的类。获取IWindowManager的代码如下:

csharp 复制代码
WindowManagerGlobal.java

public static IWindowManager getWindowManagerService() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowManagerService == null) {
            sWindowManagerService = IWindowManager.Stub.asInterface(
                    ServiceManager.getService("window"));
            try {
                if (sWindowManagerService != null) {
                    ValueAnimator.setDurationScale(
                            sWindowManagerService.getCurrentAnimatorScale());
                    sUseBLASTAdapter = sWindowManagerService.useBLAST();
                }
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return sWindowManagerService;
    }
}
  1. App获取IWindowSession接口

    每个 App 进程都有一个公用的 IWindowSession,保存在 WindowManagerGlobal 中。可通过 adb shell dumpsys window s 查看所有 session,获取代码如下:

java 复制代码
    WindowManagerGlobal.java

    @UnsupportedAppUsage
    public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    // Emulate the legacy behavior.  The global instance of InputMethodManager
                    // was instantiated here.
                    // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage
                    InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
                    IWindowManager windowManager = getWindowManagerService();
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            });
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowSession;
        }
    }
  1. 窗口添加的核心实现

    窗口添加通过 IWindowSessionaddView 接口完成。添加时,App 需向 WMS 提供 IWindow 接口,使 WMS 能通过该接口通知 App 窗口状态的变化。

graph LR subgraph System_Server; WMS; end; subgraph App; View; Activity; Dialog; end; App --IWindowManager--> WMS; App --IWindowSession--> WMS; WMS --IWindow--> View;

从上图可以看出,App(client端)和WMS(Server端)双向通信通道建立完成。

三、窗口添加完整流程

  1. 以 addView 添加 View 为例
sequenceDiagram App->>Context: getSystemService Context->>SystemServiceRegistry:getSystemService: SystemServiceRegistry->>CachedServiceFetcher:getService CachedServiceFetcher->>WindowManagerImpl:new App->>WindowManagerImpl:addView WindowManagerImpl->>WindowManagerGlobal: addView WindowManagerGlobal->>WindowManagerGlobal:getWindowSession WindowManagerGlobal->>ViewRootImpl: new ViewRootImpl() ViewRootImpl->>ViewRootImpl: new IWindow() WindowManagerGlobal->>ViewRootImpl: setView ViewRootImpl->>IWindowSession: addToDisplayAsUser

addToDisplayAsUser通过bind调用到WMS完成了窗口的添加。

  1. Dialog 和 Activity 的窗口添加

    Dialog 和 Activity 的窗口添加流程稍复杂,二者均对应一个 Window 实例。Window 是对窗口公共属性(如标题、背景、菜单等)的抽象,PhoneWindow 是其具体实现。PhoneWindow 包含核心的 DecorView,而 DecorView 正是通过 WindowManager.addView 添加的 View。PhoneWindow 调用 generateDecor 时,会根据主题和特性加载不同的布局与属性。

sequenceDiagram Activity->>Activity: attach Activity->>PhoneWindow: new Activity->>PhoneWindow: setContentView ActivityThread->>Activity: handleResumeActivity Activity->>PhoneWindow: getDectorView PhoneWindow->>PhoneWindow: installDector PhoneWindow->>PhoneWindow: generateDecor Activity->>Activity: makeVisible Activity->>WindowManagerImpl: addView

WindowManagerImpl.addView 之后的流程与前文 addView 方式一致。

备注:以上代码分析以Android 14代码为准

相关推荐
柯南二号1 小时前
【Android】【设计模式】抽象工厂模式改造弹窗组件必知必会
android·设计模式·抽象工厂模式
TsengOnce7 小时前
MySQL 性能调优与 SQL 优化的核心利器
android·sql·mysql
熊大与iOS8 小时前
iOS 长截图的完美实现方案 - 附Demo源码
android·算法·ios
独行soc9 小时前
2025年渗透测试面试题总结-42(题目+回答)
android·数据库·安全·adb·面试·渗透测试·sqlite
千里马学框架10 小时前
安卓15 audio新专题发布:安卓系统手机车机音频audio子系统深入实战开发专题
android·智能手机·音视频
没有了遇见11 小时前
Android 虚拟环境之虚拟环境检测<完结版>
android
liang_jy11 小时前
Android 单元测试(二)—— 高级 Mock 技术
android·面试·单元测试
liang_jy12 小时前
Android 单元测试(一)—— 基础
android·面试·单元测试
Digitally13 小时前
如何将照片从电脑传输到安卓设备
android·电脑