一、窗口的三种形式
- Activity:独立的页面窗口,拥有完整生命周期。这种是最常用的方式。
- 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也可以通过这种方式添加浮动窗口。
二、核心接口
- 
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;
    }
}- 
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;
        }
    }- 
窗口添加的核心实现 窗口添加通过 IWindowSession的addView接口完成。添加时,App 需向 WMS 提供IWindow接口,使 WMS 能通过该接口通知 App 窗口状态的变化。
从上图可以看出,App(client端)和WMS(Server端)双向通信通道建立完成。
三、窗口添加完整流程
- 以 addView 添加 View 为例
addToDisplayAsUser通过bind调用到WMS完成了窗口的添加。
- 
Dialog 和 Activity 的窗口添加 Dialog 和 Activity 的窗口添加流程稍复杂,二者均对应一个 Window实例。Window是对窗口公共属性(如标题、背景、菜单等)的抽象,PhoneWindow是其具体实现。PhoneWindow包含核心的DecorView,而DecorView正是通过WindowManager.addView添加的 View。PhoneWindow调用generateDecor时,会根据主题和特性加载不同的布局与属性。
WindowManagerImpl.addView 之后的流程与前文 addView 方式一致。
备注:以上代码分析以Android 14代码为准