【Android源码】AlertDialog 源码分析
Android系统封装了AlertDialog,用来给我们使用。我们可以通过
AlertDialog.Builder builder = new AlertDialog.Builder(this).setTitle("Title").setMessage("message").create().show();
复制代码
这个其实就是典型的Builder设计模式,通过封装复杂的dialog对象,将组建和构建分离,当用户使用的时候可以直接调用组建,并最后创建出Dialog对象。
通过Dialog源码的分析,我们能够更好的了解Builder设计模式。
public class AlertDialog extends Dialog implements DialogInterface {private AlertController mAlert;AlertDialog(Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0,createContextThemeWrapper);mWindow.alwaysReadCloseOnTouchAttr();mAlert = new AlertController(getContext(), this, getWindow());}@Overridepublic void setTitle(CharSequence title) {super.setTitle(title);mAlert.setTitle(title);}public static class Builder {public Builder(Context context, int themeResId) {P = new AlertController.AlertParams(new ContextThemeWrapper(context, resolveDialogTheme(context, themeResId)));}public Builder setTitle(@StringRes int titleId) {P.mTitle = P.mContext.getText(titleId);return this;}public AlertDialog create() {// Context has already been wrapped with the appropriate theme.final AlertDialog dialog = new AlertDialog(P.mContext, 0, false);P.apply(dialog.mAlert);dialog.setCancelable(P.mCancelable);if (P.mCancelable) {dialog.setCanceledOnTouchOutside(true);}dialog.setOnCancelListener(P.mOnCancelListener);dialog.setOnDismissListener(P.mOnDismissListener);if (P.mOnKeyListener != null) {dialog.setOnKeyListener(P.mOnKeyListener);}return dialog;}public AlertDialog show() {final AlertDialog dialog = create();dialog.show();return dialog;}}
}
复制代码
通过上面的代码我们可以看到,创建AlertDialog.Build的时候会创建一个AlertController.AlertParams对象,这个对象里面封装了所有的Dialog的属性,并且在调用Builder的类似于setTitle方法的时候会将参数赋值给AlertParams,当所有的组件的属性赋值好之后,就调用create()方法,这个方法里面就创建出AlertDialog对象,并调用P.apply(dialog.mAlert)方法,将AlertDialog构造函数创建出来的AlertController对象传递给P:
public void apply(AlertController dialog) {if (mCustomTitleView != null) {dialog.setCustomTitle(mCustomTitleView);} else {if (mTitle != null) {dialog.setTitle(mTitle);}if (mIcon != null) {dialog.setIcon(mIcon);}if (mIconId != 0) {dialog.setIcon(mIconId);}if (mIconAttrId != 0) {dialog.setIcon(dialog.getIconAttributeResId(mIconAttrId));}}// 代码省略
}
复制代码
在apply方法中,可以发现只是把AlertParams中的参数设置到AlertController中,当我们调用create方法的时候,就是讲AlertDialog对象的组件组装起来,当我调用show的时候就会调用dialog的show方法:
public void show() {// 如果已经在显示状态,returnif (mShowing) {if (mDecor != null) {if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR);}mDecor.setVisibility(View.VISIBLE);}return;}mCanceled = false;if (!mCreated) {dispatchOnCreate(null);}onStart();// 获取DecorViewmDecor = mWindow.getDecorView();// 获取布局参数WindowManager.LayoutParams l = mWindow.getAttributes();if ((l.softInputMode& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {WindowManager.LayoutParams nl = new WindowManager.LayoutParams();nl.copyFrom(l);nl.softInputMode |=WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;l = nl;}// 将decorView添加到WindowManager中mWindowManager.addView(mDecor, l);mShowing = true;// 发送一个现实Dialog的消息sendShowMessage();
}
复制代码
在show方法中:
通过diapatchOnCreate方法,调用Dialog的onCreate方法,并最终调用installContent方法。
public void installContent() {/* We use a custom title so never request a window title */mWindow.requestFeature(Window.FEATURE_NO_TITLE);// 设置窗口的视图int contentView = selectContentView();mWindow.setContentView(contentView);setupView();setupDecor(); } private int selectContentView() {if (mButtonPanelSideLayout == 0) {return mAlertDialogLayout;}if (mButtonPanelLayoutHint == AlertDialog.LAYOUT_HINT_SIDE) {return mButtonPanelSideLayout;}// TODO: use layout hint side for long messages/listsreturn mAlertDialogLayout; } 复制代码
而我们可以看到在调用selectContentView的时候,会去获取mButtonPanelSideLayout视图,并通过WindowManager的setContentView方法来将视图加载。
public AlertController(Context context, DialogInterface di, Window window) {final TypedArray a = context.obtainStyledAttributes(null,R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);// 获取视图mAlertDialogLayout = a.getResourceId(R.styleable.AlertDialog_layout, R.layout.alert_dialog);a.recycle(); } 复制代码
再通过setupView方法初始化AlertDialog布局中的各个部分
调用AlertDialog的onStart方法
最后将DecorView添加到WindowManager中
【Android源码】AlertDialog 源码分析相关推荐
- Android 系统(78)---《android framework常用api源码分析》之 app应用安装流程
<android framework常用api源码分析>之 app应用安装流程 <android framework常用api源码分析>android生态在中国已经发展非常庞大 ...
- Android Camera 系统架构源码分析
Android Camera 系统架构源码分析(1)---->Camera的初始化 Android Camera 系统架构源码分析(2)---->Camera的startPreview和s ...
- Android 8.0系统源码分析--开篇
个人分类: Android框架总结Android源码解析android framework 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/sinat ...
- Android+上百实例源码分析以及开源分析+集合打包
1.360新版特性界面源代码 实现了360新版特性界面的效果,主要涉及到Qt的一些事件处理与自定义控件.但源码好像是c++. 2.aidl跨进程调用 服务端onBind暴露,然后客户端bindServ ...
- Android 11.0 Settings源码分析 - 主界面加载
Android 11.0 Settings源码分析 - 主界面加载 本篇主要记录AndroidR Settings源码主界面加载流程,方便后续工作调试其流程. Settings代码路径: packag ...
- Android录音下————AudioRecord源码分析
Android录音下----AudioRecord源码分析 文章目录 Android录音下----AudioRecord源码分析 一.概述 1.主要分析点 2.储备知识 二.getMinBufferS ...
- Android WIFI调试助手源码分析
**WIFI调试助手源码(支持十六进制和ACSII发送与接收) 客户端(我自己修改的工程文件,支持十六制的接收与发送,主要是通信协议,代码简单,可轻松改造为上位机) ** 分为操作分析和代码分析. 1 ...
- Android上百实例源码分析以及开源分析集合打包
感谢网友banketree的收集,压缩包的内容如下: 1.360新版特性界面源代码 实现了360新版特性界面的效果,主要涉及到Qt的一些事件处理与自定义控件.但源码好像是c++. 2.aidl跨进程调 ...
- Android 8.0系统源码分析--Camera processCaptureResult结果回传源码分析
相机,从上到下概览一下,真是太大了,上面的APP->Framework->CameraServer->CameraHAL,HAL进程中Pipeline.接各种算法的Node.再往下的 ...
- Android 双开沙箱 VirtualApp 源码分析(一)
最近发现了一个非常好的开源项目,基本实现了一个 Android 上的沙箱环境,不过应用场景最多的还是应用双开. VA github: https://github.com/asLody/Virtual ...
最新文章
- Matlab数据的可视化 -- 图形格式的设置
- OpenStack看到中国“钱”景
- 右手螺旋判断磁感应强度方向_高考丨电磁感应丨感应电动势
- 小微企业——客户借款原因分析
- JavaScript学习(六十)—JSON
- python求立方尾不变_蓝桥杯—立方尾不变,有些数字的立方的末尾正好是该数字本身...
- ftp和http转参数的使用(转)
- Android 蓝牙键盘快捷键
- %02x与%2x 区别
- 码支付源码完整版-安装环境配置
- 面向对象,面向对象的优点
- (转)Ogre 天龙八部 GridInfo文件格式说明(正确版)
- 如何通俗理解并快速写出麦克斯韦方程组?
- 如何利用laragon框架制作一个简单的应用?
- 基于Singer混沌映射的麻雀搜索算法-附代码
- CentOS7快速搭建DNS中转服务器
- 生化实验技术——酵母双杂交
- 路径规划算法学习Day5
- Django项目使用wangeditor方法
- 大学英语4级该如何有效的学习?
热门文章
- get post put delete 区别_GET 和 POST 的区别?
- linux下redis安装教程,linux下安装配置redis图文详解
- seo说_百度指数看世间沉浮_如何快速排名-互点快速排名_网站关键词排名常见问题 - 搜狗快速排名...
- jquery实现表格拖拽排序
- mysql快速迁移数据sql_使用Navicat Premium工具快速迁移数据方法 适用于mysql及mssql数据库...
- bios设置 联想m8000t_联想怎样设置双显卡模式 联想设置双显卡模式方法【详解】...
- client软件怎么卸载 nac_如何彻底卸载在 Mac 上安装的一个软件?
- 范德蒙德矩阵在MATLAB中怎么表示,Python 之 Python与MATLAB 矩阵操作总结
- springboot整合springSecurity使用
- Java设计模式(代理模式-模板方法模式-命令模式)