前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android:源码解析 Dialog的窗口机制

Android:源码解析 Dialog的窗口机制

作者头像
Carson.Ho
发布2020-08-12 11:00:07
1.5K0
发布2020-08-12 11:00:07
举报
文章被收录于专栏:Android知识分享

概述

本文将通过 Dialog 的创建、展示 & 销毁过程源码, 详细说明 Dialog 的窗口机制

分析内容

代码语言:javascript
复制
// 1. 创建
Dialog dialog = new ProgressDialog(context);

// 2. 展示
dialog.show();

// 3. 销毁
dialog.cancel();
dialog.dmiss();

Dialog创建

  1. Dialog一般在Acitivty启动,所以传入的是Activity的Context
  2. 任何创建方法都是基于Dialog基类,所以下面分析的源码是Dialog基类
代码语言:javascript
复制
// 具体使用
Dialog dialog = new ProgressDialog(context);

// 源码分析
public class Dialog implements DialogInterface, Window.Callback,KeyEvent.Callback, OnCreateContextMenuListener, Window.OnWindowDismissedCallback {
    // ...

    // 构造函数最终都调运了该默认的构造函数
    Dialog(Context context, int theme, boolean createContextThemeWrapper) {
    // mContext参数是创建时从外部传入的Activity context对象值

    // 步骤1. 获取WindowManager对象
    mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);

    // 步骤2. 为Dialog创建新的Window
    Window w = PolicyManager.makeNewWindow(mContext);
    mWindow = w;

    // 步骤3. 关联WindowManager与新Window
    // 注:第二个参数token为null,即一个Window属于Dialog的话,那么该Window的传入的mAppToken对象是null,Dialog没有自己的token
    w.setWindowManager(mWindowManager, null, null);
    }
    ......
}

源码说明

  • 步骤1:因为 context 是Activity,所以获取到的 WindowManager 属于 Activity,所以** Dialog 与 Activity 共用一个 WindowManager 对象**
  • 步骤2:获得 Activity 的WindowManager对象后,Dialog 又新建了一个 Window对象(PhoneWindow 类型,创建过程类似于 Activity 的 Window 创建过程)
  • 步骤3:将新创建 Dialog 的 window 关联到 Activity 的 WindowManager。特别注意的是:关于AppToken,只是Window的传入的mAppToken对象是null,但不代表Dialog的window无token,下面会详细说明

重要结论

  • 结论1:Dialog 与 Activity 共用一个 WindowManager 对象
  • 结论2:Dialog 拥有自己的窗口 Window(PhoneWindow 类型)
  • 结论3:Dialog 的 Window 由附属的 Acitivty WindowManager 对象统一管理

Dialog展示

代码语言:javascript
复制
// 具体使用
dialog.show();

// 源码分析
public void show() {
    // ....

    // 1. 调用 Dialog的onCreate()
    dispatchOnCreate(null);

    // 2. 调用Dialog的onStart()
    onStart();

    // 3. 获取当前新Window的DecorView对象(类似于Activity)
    mDecor = mWindow.getDecorView();

    // 4. 获取新Window的WindowManager.LayoutParams参数
    WindowManager.LayoutParams l = mWindow.getAttributes();

    // 5. 把一个View添加到与Activity共用的windowManager里
    mWindowManager.addView(mDecor, l);

}

源码分析

  • 步骤3:Dialog获取当前新Window的DecorView对象时过程类似于Activity,所以有一种自定义Dialog布局的方式就是重写Dialog的onCreate方法,使用setContentView传入布局,类似于 Activity。
  • 步骤4:由于Dialog 与 Activity 共用一个 WindowManager 对象,所以Activity与Dialog共用同一个mAppToken值(只是Dialog和Activity的Window对象不同)。
  • 步骤5:添加过程与Activity 窗口添加过程 保持一致。

Dialog 销毁

既然添加过程与Activity 窗口添加过程 保持一致,那么不展示 / 销毁过程也是跟Activity 窗口销毁过程 十分类似

代码语言:javascript
复制
// 具体使用
dialog.cancel();
dialog.dmiss();

// 源码分析
// 上述两个方法最终都会回调:dismissDialog()
void dismissDialog() {
    //... 
    mWindowManager.removeViewImmediate(mDecor);
}

mWindowManager 实际上是 WindowManagerImpl 的实例,所以这里的 removeViewImmediate()就是 WindowManagerImpl 中移除 View 的方法,跟Activity 窗口销毁过程 十分类似,这里就不继续展开说明了。

关于Dialog的窗口机制讲解到这里

请点赞!因为你的鼓励是我写作的最大动力!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/08/11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 分析内容
  • Dialog创建
    • 源码说明
      • 重要结论
      • Dialog展示
        • 源码分析
        • Dialog 销毁
        • 请点赞!因为你的鼓励是我写作的最大动力!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档