Android 窗口创建流程

Android 窗口创建流程

添加一个 Window

不论是 Activity、Dialog、PopupWindow还是其他浮动窗口,屏幕上可以看到的一切窗口最终都是通过调用 WindowManager.addView(View view, ViewGroup.LayoutParams params) 方法添加的。我们在调查一个窗口的显示的时候只要找到调用WindowManager.addView()的位置就可以了,这之前的流程可以在这里打印一个调用堆栈来跟踪。

这个 addView() 方法里有两个参数:

  • View view View 树的根 View,也就是需要在窗口上显示的内容
  • ViewGroup.LayoutParams params 窗口相关的参数,实际为 WindowManager.LayoutParams,包括显示的位置、大小、层级、焦点处理标记等

WindowManager 一般通过 context.getSystemService(Context.WINDOW_SERVICE) 或者 context.getSystemService(WindowManager.class) 获得,这里最终获得的是从 SystemServiceRegistry 创建的一个 WindowManagerImpl 的实例。而 WindowManagerImpl 里又创建了一个 WindowManagerGlobal 的实例。WindowManagerImplWindowManagerGlobal 都是单实例的,即每个进程只有一个实例。

// frameworks/base/core/java/android/app/SystemServiceRegistry.java
registerService(Context.WINDOW_SERVICE, WindowManager.class,
        new CachedServiceFetcher<WindowManager>() {
   
    @Override
    public WindowManager createService(ContextImpl ctx) {
   
        return new WindowManagerImpl(ctx);
    }});

// frameworks/base/core/java/android/view/WindowManagerImpl.java
public final class WindowManagerImpl implements WindowManager {
   
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

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

addView() 方法的最终实现在 WindowManagerGlobal 里:

//frameworks/base/core/java/android/view/WindowManagerGlobal.java
public final class WindowManagerGlobal {
   
    // 三个 ArrayList 保存着这个应用里所有窗口的 View 树、ViewRootImpl 以及 窗口参数 LayoutParams
    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>();
    ...

    /**
     * 这里的几个参数:
     * View view, view 树
     * ViewGroup.LayoutParams params,窗口参数
     * Display display, 确定这个窗口需要显示到哪个屏幕,默认为主屏幕
     * Window parentWindow,父窗口
     *        Dialog、PopupWindow 等浮动窗口的父窗口为弹出它的Activity窗口,
     *        从后台 Service 启动的窗口可以没有父窗口
     */
    public void addView(View view, ViewGroup.LayoutParams params,
                            Display display, Window parentWindow) {
   
        // wparams 会给窗口再附加一些属性
        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
        ViewRootImpl root;
        // 如果将要添加的是子窗口,panelParentView 为父窗口的 View 树,用来参考设置该子窗口的显示
        View panelParentView = null;

        // 创建 ViewRootImpl
        root = new ViewRootImpl(view.getContext(), display);
        // 给 View 树关联窗口属性
        view.setLayoutParams(wparams);

        // 将 View 树、ViewRootImpl、以及窗口参数添加到各个列表里
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);

        // 将 View 树关联到 ViewRootImpl
        root.setView(view, wparams, panelParentView);
    }
}

之后的事情就都在 ViewRootImpl 里了,ViewRootImpl 的一些关键成员、方法如下面的代码:

public final class ViewRootImpl {
   
    // 与 WindowManagerService 连接的会话
    final IWindowSession mWindowSession;
    // 保存该窗口显示的屏幕
    Display mDisplay;
    // 屏幕管理服务
    final DisplayManager mDisplayManager;
    // 该窗口所归属的应用包名
    final String mBasePackageName;
    // 创建该窗口的线程,一般为主线程
    final Thread mThread;
    // 保存窗口属性参数
    public final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams();
    // 应用端的窗口代表,后面介绍
    final W mWindow;
    // 该窗口要显示的 View 树
    View mView;

    // 如下两个成员表示保存该窗口的绘画所用的画布
    public final Surface mSurface = new Surface();
    private final SurfaceControl mSurfaceControl = new SurfaceControl();

    // 记录该窗口是否第一次刷新
    
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android启动流程主要包括以下几个步骤: 1. Bootloader(引导加载程序):当我们按下 Android 设备的电源键时,系统会进入 bootloader 阶段,这个阶段主要是检测硬件设备并加载内核。 2. Kernel(内核):当 bootloader 加载完毕后,会启动内核。Android 的内核主要是 Linux 内核,它负责管理设备的硬件资源和提供基本的系统服务。 3. Init(系统初始化):在内核启动后,会运行 init 进程,它是 Android 系统的第一个用户空间进程,主要负责初始化系统环境、启动系统服务和应用程序。 4. System Server(系统服务):系统服务是 Android 系统的核心部分,它们提供了各种系统功能,例如:窗口管理、通知、电源管理等。 5. Zygote(应用程序启动):Zygote 进程是 Android 系统中的一个特殊进程,它会在系统启动时启动,并且负责创建和管理所有的应用程序进程。当我们启动一个应用程序时,Zygote 会为该应用程序创建一个新的进程,并且该进程会继承 Zygote 的一些属性和状态。 6. 应用程序进程:应用程序进程是 Android 系统中运行应用程序的最小单位,每个应用程序都会运行在一个独立的进程中,它们之间相互隔离,互不干扰。 以上是 Android 系统启动的主要流程,当然在实际的启动过程中还有很多细节需要处理,例如:启动动画、初始化硬件设备等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值