一.构建者模式
- 不熟悉构建者设计模式的童靴可以参考下面文章:
- 菜鸟教程-建造者模式
- Java设计模式之《构建者模式》及应用场景
二.源码分析
2.1.在界面中构建AlertDialog
//构建AlertDialog,sdk版本:28 android.app包下
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.drawable.ic_launcher_background)
.setTitle("头部")
.setMessage("内容")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,"点击确定按钮",Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,"点击取消按钮",Toast.LENGTH_SHORT).show();
}
})
.create()
.show();
2.2.builder创建—->setXxx—->create—->show
//AlertDialog类
public class AlertDialog extends Dialog implements DialogInterface {
private AlertController mAlert;
//省略...
//注意:根据修饰符可知,不能直接new对象
protected AlertDialog(Context context, @StyleRes int themeResId) {
this(context, themeResId, true);
}
//构造函数
AlertDialog(Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0,
createContextThemeWrapper);
mWindow.alwaysReadCloseOnTouchAttr();
mAlert = AlertController.create(getContext(), this, getWindow());
}
//省略...
// ************ 注意:Builder为AlertDialog的内部类 *******************
public static class Builder对象,调用构造函数 {
//问题: final修饰了,还是再被赋值 怎么解释呢?
private final AlertController.AlertParams P;
//1.创建Builder对象,调用构造函数
public Builder(Context context) {
this(context, resolveDialogTheme(context, ResourceId.ID_NULL));
}
public Builder(Context context, int themeResId) {
P = new AlertController.AlertParams(new ContextThemeWrapper(
context, resolveDialogTheme(context, themeResId)));
}
//省略...
//2.调用Builder对象中的setXxx方法
//设置P中的mTitle属性
public Builder setTitle(CharSequence title) {
P.mTitle = title;
return this;
}
//省略setXxx...
//3.构建AlertDialog, 传递参数
public AlertDialog create() {
// Context has already been wrapped with the appropriate theme.
//4.调用AlertDialog构造函数
final AlertDialog dialog = new AlertDialog(P.mContext, 0, false);
//5.调用AlertController类中AlertParams对象的apply方法
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;
}
//省略...
}
//省略...
}
2.3.AlertDialog的构造方法和内部类Builder
public class AlertDialog extends Dialog implements DialogInterface {
//位置二:包含AlertController对象;
private AlertController mAlert;
//...
//位置一:构造方法被protected修饰,故不能直接new(而是通过内部类Builder来构建,后面分析);
protected AlertDialog(Context context) {
this(context, 0);
}
protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
this(context, 0);
setCancelable(cancelable);
setOnCancelListener(cancelListener);
}
protected AlertDialog(Context context, @StyleRes int themeResId) {
this(context, themeResId, true);
}
//构造方法,默认的修饰符,只能在同一个包中访问
AlertDialog(Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0,
createContextThemeWrapper);
mWindow.alwaysReadCloseOnTouchAttr();
mAlert = AlertController.create(getContext(), this, getWindow());
}
//...
//位置三:内部类Builder
public static class Builder {
//位置四:包含AlertController的AlertParams对象
private final AlertController.AlertParams P;
public Builder(Context context) {
this(context, resolveDialogTheme(context, ResourceId.ID_NULL));
}
public Builder(Context context, int themeResId) {
P = new AlertController.AlertParams(new ContextThemeWrapper(
context, resolveDialogTheme(context, themeResId)));
}
//...
}
2.4.AlertController
public class AlertController {
//省略...
public static class AlertParams {
//省略...
public AlertParams(Context context) {
mContext = context;
mCancelable = true;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
//省略...
//分析二
public void apply(AlertController dialog) {
//给非空的属性赋值
//调用setView方法
}
}
//省略...
}
2.5.AlertController的create方法
public class AlertDialog extends Dialog implements DialogInterface {
//...
/**
* Creates an {@link AlertDialog} with the arguments supplied to this
* builder.
* <p>
* Calling this method does not display the dialog. If no additional
* processing is needed, {@link #show()} may be called instead to both
* create and display the dialog.
*/
public AlertDialog create() {
// Context has already been wrapped with the appropriate theme.
//创建dialog,查看构造方法 ---> 分析一
final AlertDialog dialog = new AlertDialog(P.mContext, 0, false);
//接着调用AlertController.AlertParams P的apply方法(相当于组装步骤) ---> 分析二
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;
}
//...
AlertDialog(Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0,
createContextThemeWrapper);
mWindow.alwaysReadCloseOnTouchAttr();
//分析一 : AlertDialog中包含mAlert对象,传入参数:上下文,DialogInterface,Window
mAlert = AlertController.create(getContext(), this, getWindow());
}
}
2.6.包含关系展示
![dialog源码分析.png](/uploads/projects/xiaoyuer-p3kfo@zhuanti/6dca4830f0d8892961c3eb79b38dd707.png)
- AlertDialog —> 包含Builder类;
- AlertDialog构造方法中初始化AlertController对象;
- Builder类中初始化AlertParams对象;
- AlertController —> 包含AlertParams类;
- Builder同时扮演了抽象的builder、具体的ConcreteBuilder、指挥者Director(直接采用链式调用,省去了Director)的角色,简化了Builder模式的设计;
- AlertDialog(电脑对象)
- AlertDialog.Builder 规范一系列的组装过程
- AlertController 具体的构建器
- AlertController.AlertParams 存放参数,一部分设置参数的功能
- show方法在Dialog中查看.
三.打造dialog
- 根据2.6图中的包含关系可知,我们需要定义两个类,AlertDialog和AlertController,其中AlertDialog类中会定义一个内部类Builder,AlertController会定义一个内部类AlertParams.
- 生成的AlertDialog对象需要设置的属性,都放在AlertController内部类AlertParams中作为内部类变量,AlertParams中的变量通过Builder中设定setXxx方法来设置.
- 属性都定义好之后,通过builder中的方法来生成AlertDialog对象.
- 额外创建一个工具类,打造的对话框一共有三个类.
四.源码
github地址